有限状态自动机

news2024/11/23 15:23:39

1 什么是有限状态自动机

1.1什么是计算

维基百科定义计算(英语:Calculation)是一种将“单一或多个的输入值”转换为“单一或多个的结果”的一种思考过程。可以简单理解为给出一个问题得到一个答案的过程。如下图所示日常生活比较常见计算问题:
在这里插入图片描述

1.2 判定问题
维基百科定义:在可计算性理论与计算复杂性理论中,决定性问题,亦称判定问题,(英语:Decision problem)是一个在某些形式系统回答“是”或“否”的问题。
在可计算理论中,会把相关计算问题最终转化为判定问题,如下图所示,比如求正方形面积如何转成判定问题,边长为4的正方向面积,边长为4面积是1、2、3…输入到判定器去判断(可计算理论中不考虑性能)最终16时候判定器会接受。
在这里插入图片描述

1.3 有限状态自动机
维基百科给出的定义:有限状态机(finite state machine, FSM)又称为有限状态自动机(finite state automaton,FSA)简称状态机,是表示有限个状态以及在这些状态之间的转移和动作作为行为的数学计算模型。
从定义可以FSM是一个计算模型;它的状态是有限的(可枚举的),自动机是这个状态之间的转移行为,最后的结果判断这一系列行为是否符可接受要求。
有限状态自动机的数学模型,五元组M=(S,I,f,A,S0),其中
● S是一个有限的状态集合
● I是一个有限输入符号结合
● f表示状态的转换是从SXI到S的函数
● A表示接受状态非空集合A包含于S
● S0表示初始状态,S0属于S
起初,这个自动机处于「初始状态」。随后,它顺序地读取字符串中的每一个字符,并根据当前状态和读入的字符,按照某个事先约定好的「转移规则」,从当前状态转移到下一个状态;当状态转移完成后,它就读取下一个字符。当字符串全部读取完毕后,如果自动机处于某个「接受状态」,则判定该字符串「被接受」;否则,判定该字符串「被拒绝」。
例子:给定一个字符串str=“111011010010”,通过构建一个有限状态自动机,来判定是否满足偶数个1。
● 有限状态有两个:奇数个1和偶数个1,即:S={EVEN_ONE,ODD_ONE};
● I={“111011010010”}
● 状态转移函数,和当前状态S和输入有关;转移函数如下

在这里插入图片描述

class Solution {
    private static Map<State, Map<Character, State>> transferMap = new HashMap<>();

    static {
        Map<Character, State> evenOneMap = new HashMap<>();
        evenOneMap.put('1', State.ODD_ONE);
        evenOneMap.put('0', State.EVEN_ONE);
        transferMap.put(State.EVEN_ONE, evenOneMap);
        Map<Character, State> oddOneMap = new HashMap<>();
        oddOneMap.put('1', State.EVEN_ONE);
        oddOneMap.put('0', State.ODD_ONE);
        transferMap.put(State.ODD_ONE, oddOneMap);
    }

    //状态
    enum State {
        EVEN_ONE,//偶数个1,可接受状态
        ODD_ONE//奇数个1
    }

    public boolean recognize(String input) {
        if (input == null) {
            return true;
        }
        //初始状态 0个1也是偶数个1
        State currentState = State.EVEN_ONE;
        for (int i = 0; i < input.length(); i++) {
            currentState = transfer(input.charAt(i), currentState);
            //如果存在转移不了状态直接终止
            if (currentState == null) {
                break;
            }
        }
        return currentState == State.EVEN_ONE;
    }

    private State transfer(char currentChar, State currentState) {
        return transferMap.get(currentState).get(currentChar);
    }
}

2 代码实战

https://leetcode.cn/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/description/

class Solution {
    private static Map<State, Map<CharType, State>> transferMap = new HashMap<>();
    private static Set<State> acceptStateSet=new HashSet<>();
    static {
        //
        Map<CharType, State> initialMap = new HashMap<>();
        initialMap.put(CharType.SPACE, State.INITIAL);
        initialMap.put(CharType.SIGN, State.SIGN);
        initialMap.put(CharType.NUMBER, State.INTEGER);
        initialMap.put(CharType.POINT, State.POINT_WITHOUT_INT);
        transferMap.put(State.INITIAL, initialMap);

        Map<CharType, State> signMap = new HashMap<>();
        signMap.put(CharType.NUMBER, State.INTEGER);
        signMap.put(CharType.POINT, State.POINT_WITHOUT_INT);
        transferMap.put(State.SIGN, signMap);

        Map<CharType, State> integerMap = new HashMap<>();
        integerMap.put(CharType.NUMBER, State.INTEGER);
        integerMap.put(CharType.POINT, State.POINT_HAS_INT);
        integerMap.put(CharType.EXP, State.EXP);
        integerMap.put(CharType.SPACE, State.END);
        transferMap.put(State.INTEGER, integerMap);

        Map<CharType, State> pointHasIntMap = new HashMap<>();
        pointHasIntMap.put(CharType.NUMBER, State.FRACTION);
        pointHasIntMap.put(CharType.EXP, State.EXP);
        pointHasIntMap.put(CharType.SPACE, State.END);
        transferMap.put(State.POINT_HAS_INT, pointHasIntMap);

        Map<CharType, State> pointWithoutIntMap = new HashMap<>();
        pointWithoutIntMap.put(CharType.NUMBER, State.FRACTION);
        transferMap.put(State.POINT_WITHOUT_INT, pointWithoutIntMap);

        Map<CharType, State> fractionMap = new HashMap<>();
        fractionMap.put(CharType.NUMBER, State.FRACTION);
        fractionMap.put(CharType.EXP, State.EXP);
        fractionMap.put(CharType.SPACE, State.END);
        transferMap.put(State.FRACTION, fractionMap);

        Map<CharType, State> expMap = new HashMap<>();
        expMap.put(CharType.NUMBER, State.EXP_NUMBER);
        expMap.put(CharType.SIGN, State.EXP_SIGN);
        transferMap.put(State.EXP, expMap);

        Map<CharType, State> expSignMap = new HashMap<>();
        expSignMap.put(CharType.NUMBER, State.EXP_NUMBER);
        transferMap.put(State.EXP_SIGN, expSignMap);

        Map<CharType, State> expNumberMap = new HashMap<>();
        expNumberMap.put(CharType.NUMBER, State.EXP_NUMBER);
        expNumberMap.put(CharType.SPACE, State.END);
        transferMap.put(State.EXP_NUMBER, expNumberMap);

        Map<CharType, State> endMap = new HashMap<>();
        endMap.put(CharType.SPACE, State.END);
        transferMap.put(State.END, endMap);

        acceptStateSet.add(State.INTEGER);
        acceptStateSet.add(State.END);
        acceptStateSet.add(State.EXP_NUMBER);
        acceptStateSet.add(State.FRACTION);
        acceptStateSet.add(State.POINT_HAS_INT);
    }

    enum State {
        INITIAL, //初始化,
        SIGN,//符号位
        INTEGER,//整数部分--可接受状态
        POINT_HAS_INT,//小数点左侧有整数如:2. --可接受状态
        POINT_WITHOUT_INT,//小数点左侧有无整数如:.3
        FRACTION,//小数部分 ---可接受状态
        EXP,//指数E,e
        EXP_SIGN,//指数符号位
        EXP_NUMBER,//指数后面整数----可接受状态
        END//末尾空格----可接受状态
    }

    enum CharType {
        NUMBER, //数字
        EXP,//指数E或者e
        POINT,//小数点
        SIGN,//符号
        SPACE,//空格
        ILLEGAL//非法
    }

    public boolean isNumber(String input) {
        if (input == null) {
            return true;
        }
        State currentState = State.INITIAL;
        for (int i = 0; i < input.length(); i++) {
            currentState = transfer(input.charAt(i), currentState);
            //如果存在转移不了状态直接终止
            if (currentState == null) {
                break;
            }
        }
        return acceptStateSet.contains(currentState);
    }

    //转移函数
    private State transfer(char currentChar, State currentState) {
        CharType charType = toCharType(currentChar);
        return transferMap.get(currentState).get(charType);
    }

    private CharType toCharType(char currentChar) {
        if (currentChar >= '0' && currentChar <= '9') {
            return CharType.NUMBER;
        } else if (currentChar == 'E' || currentChar == 'e') {
            return CharType.EXP;
        } else if (currentChar == '.') {
            return CharType.POINT;
        } else if (currentChar == ' ') {
            return CharType.SPACE;
        } else if (currentChar == '+' || currentChar == '-') {
            return CharType.SIGN;
        }
        return CharType.ILLEGAL;
    }
}

3 对实际工作的启发

状态机是由事件、状态、动作三大部分组成。三者的关系是:事件触发状态的转移,状态的转移触发后续动作的执行。其中动作不是必须的,也可以只进行状态转移,不进行任何操作。如下图所示,可以受状态机启发对营销活动状态流转进行改造。
在这里插入图片描述
在这里插入图片描述

参考文献
[1] 万门大学,有限状态自动机课程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/783440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AITO问界,先经沧海而后造船

IT领域最重要的原则之一&#xff0c;就是软件快速迭代。 对于科技产品来说&#xff0c;需求永远在升级。一项技术或软件系统问世之后&#xff0c;如果后续不再迭代&#xff0c;结果可能是灾难性的。 比如几年前&#xff0c;很多读者可能都买过一些“不了了之”的智能消费硬件&a…

性能测试Ⅳ

在进行性能测试的时候需要使用不同阶段的数据来测试&#xff0c;分析不同数据下资源的情况。 java -jar -Xms1M -Xmx1M -XX:MaxMetaspaceSize10m DBPlus-0.0.1-SNAPSHOT.jar 最小内存 最大内存 如果内存太小会导致内存泄露 启动程序 java -Djava.rmi.serv…

JavaWeb课程设计项目实战(09)——项目编码实践6

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 在本节教程中&#xff0c;我们实现修改学生的功能。当在学生列表页面点击修改后首先将依据id查询该生的详细信息&#xff0c;然后将这些信息展示在修改页面。当完成学生信息…

Transformer Encoder (Bert)

参考&#xff1a;图解Self-Attention_子燕若水的博客-CSDN博客 举个例子&#xff1a; 假设输入数据形状为(243,34),表示的是243帧,每帧包含34个特征(比如17个关键点的x,y坐标)。那么这个数据在Transformer Encoder中的流动过程如下: 输入数据shape是(243, 34),表示243个时间…

【字符流】案例:点名器

案例&#xff1a;点名器 1.需求&#xff1a; 我有一个文件里面存储了班级同学的姓名&#xff0c;每一个姓名占一行&#xff0c;要求通过程序实现随机点名器 2.思路&#xff1a; 创建字符缓冲输入流对象创建ArrayList集合对象调用字符缓冲输入流对象的方法读数据把读取到的字…

vue ---- filters过滤器中不能使用this问题

在日常开发中&#xff0c;使用filters是很正常&#xff0c;最近遇到切换单位&#xff0c;页面上显示的数据要根据单位转换&#xff0c;这时就需要根据data里面的变量去转换&#xff0c;可是filters里面不能使用this 解决&#xff1a; 1、先在return中声明一个变量that&#xf…

vuejs源码之模版编译原理

之前我们说过虚拟dom&#xff0c;也就是虚拟dom拿到vnode后所做的事情&#xff0c;而模版编译是如何让虚拟dom拿到vnode。 模版编译的目标就是生成渲染函数&#xff0c;而渲染函数的作用是每次执行它&#xff0c;它就会使用当前最新的状态生成一份新的vnode&#xff0c;然后用…

========Java基础——小结1========

一、Java 两大版本 Java 主要分为两个版本: Java SE 和Java EE。 Java SE 全称Java Platform Standard Edition&#xff0c;是 Java 的标准版&#xff0c;主要用于桌面应用程序开发&#xff0c;它包含了 Java 语言基础、JDBC (Java 数据库连接)、I/O (输入/输出)、TCP/IP 网络…

【问题记录】Ubuntu 22.04 环境下,程序报:段错误(核心已转储)怎么使用 core 文件和GDB调试器 解决?

目录 环境 问题情况 解决思路 原因分析 解决方法 番外知识 环境 VMware Workstation 16 Pro &#xff08;版本&#xff1a;16.1.2 build-17966106&#xff09;ubuntu-22.04.2-desktop-amd64 问题情况 本人在运行百万并发的服务端程序时&#xff0c;程序运行报&#xff1a…

语音基石模型Speech Foundation Models

语音基石模型&#xff08;Speech Foundation Models&#xff09; 主要包含三部分&#xff1a; 1.语音表示学习&#xff08;Speech representation learning&#xff09; 自监督学习模型&#xff08;Self-suprevised learning, SSL model&#xff09;Representation benchmark…

CMU 15-445 -- Embedded Database Logic - 12

CMU 15-445 -- Embedded Database Logic - 12 引言User-Defined Functions (UDF)SQL FunctionsExternal Programming Language Stored ProceduresStored Procedures 与 UDF 的区别 Database TriggersChange NotificationsUser-Defined Types (UDT)Viewsviews vs select...intov…

区别出过孔的内径、外径、单边孔环、电镀铜厚

自记&#xff1a; 这个参数是啥&#xff1f;下图区别出过孔的内径、外径、单边孔环、电镀铜厚 嘉立创单双面最小过孔内径0.3mm/外径0.6mm&#xff08;极限0.56mm&#xff09;&#xff0c;四、六层最小过孔内径0.2mm/外径0.45mm&#xff08;极限0.40mm&#xff09;&#xff0c;外…

学习day50

自定义指令总结&#xff1a; 一&#xff1a;定义语法&#xff1a; (1)局部指令&#xff1a; new Vue({ directives{指令名&#xff0c;配置对象} }) 或 new Vue({ directives{指令名&#xff0c;回调函数} }) (2)全局对象 Vue.dir…

基于Gym Anytrading 的强化学习简单实例

近年来强化学习(RL)在算法交易领域受到了极大的关注。强化学习算法从经验中学习并基于奖励优化行动使其非常适合交易机器人。在这篇文章&#xff0c;我们将简单介绍如何使用Gym Anytrading环境和GME (GameStop Corp.)交易数据集构建一个基于强化学习的交易机器人。 强化学习是…

【Java从0到1学习】05 Java 数组

1. 数组概述 需求&#xff1a;现在需要统计某公司员工的工资情况&#xff0c;例如计算平均工资、找到最高工资等。假设该公司有80名员工&#xff0c;用前面所学的知识&#xff0c;程序首先需要声明80个变量来分别记住每位员工的工资&#xff0c;然后在进行操作&#xff0c;这样…

MySQL一些知识

六、MySQL命令参数 七、远程登录 use mysql 八、SQL语句和常见的SQL操作 九、数据库和表的创建及插入 指定字段名称&#xff0c;按照表的字段名称顺序写&#xff1a; 指定字段名称&#xff1a; 字段名称可以不全部指定&#xff1a;

SpringBoot(三)

文章目录 前言一.日志的作用二.日志的使用2.1 自定义日志打印三.日志的级别3.1 日志级别的作用3.2 日志级别的分类和使用 四.⽇志持久化 前言 日志在应用程序中扮演着至关重要的角色&#xff0c;它是软件开发、运维和故障排查中不可或缺的工具。无论是大型企业级应用还是小型个…

node插件的安装、HTTP协议

接口测试与UI测试&#xff08;功能测试&#xff0c;UI的自动化测试&#xff09;有什么区别&#xff1f; 1、接口测试更多测试的是客户端与后端之间的交互 2、接口测试也是可以完全的测试产品功能测试场景 UI测试&#xff1a; 1、页面的交互 2、页面的各种提示信息的验证 …

C#栈、List结构的简单搭建

1、栈是一种先进后出的结构&#xff0c;如图&#xff1a; 我们用代码&#xff0c;简单实现一下&#xff1a; public class StackTest<T>{private T[] stack { get; set; }public int length { get; set; }public StackTest(){length 0;stack new T[length];}public vo…

[JVM]String str1 = new String(“yhz“)和 String str2 = “yhz“ 的区别

文章目录 0、前情1、相同之处2、不同之处3、解释前情 0、前情 为什么str1 str2 就返回true&#xff0c;而str1str3 就返回false&#xff1f;先看内存图解释 1、相同之处 String str1new String(“yhz”)和String str2“yhz”&#xff0c;都会先去字符串常量池中查看是否已经存…