剑指20-表示数值的字符串

今天刷到一个贼恶心的题目, 大佬k神 的有穷状态机解法令我大开眼界。特此作文以记之。

文章目录

  • 题目描述
  • 一、有穷状态机图
  • 二、使用哈希表存储状态
  • 三、转换逻辑


题目描述

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。


字符串匹配问题常可以使用状态机来解,画状态机不算难,但是像这样条件复杂就很难,之前做到第19题就有NFA的解法,我嫌弃太难不想钻研,等下次再发那篇的解法。
剑指20-表示数值的字符串_第1张图片
mark一下。

一、有穷状态机图

剑指20-表示数值的字符串_第2张图片
这是大佬的图。
其中,2, 3,7,8都是合法的结束状态。

3表示 1.这样的数字,也是合法的

由下左的图可知,输入是有确定的范围的,因此输入有穷状态机。

难点在于,如何将状态机转化为程序呢

二、使用哈希表存储状态

状态的转换需要这样的步骤:

  1. 知晓当前的状态;
  2. 知晓当前的输入;
  3. 知晓接收这个输入之后会进入的状态。

常使用哈希表作为状态转换表的单元
使用一个数组来存储这些单元,这样:

  • 数组下标可以对应状态对应的码,如同上图右下角所示;
  • 一个HashMap可以表示这个状态接受了某输入会转化为什么输出,

因此HashMap的键应该作为输入,为了表达方便,使用左下表缩写代表输入,即用char就能表示;
使用数字表示下一个的状态,对应到达的数组下标。

综上:

  • HashMap[], 状态转换表;
  • HashMap:状态;
  • int p 当前状态(在数组的下标)
  • Hash’key, 当前接受的输入
  • Hash’value, 当前状态转换到的状态

三、转换逻辑

(一)初始化:
初始化的状态为0;

(二)遍历
遍历传入地String,对每个字符进行判断:
按照传入地类型进入下一状态,并将p更新。


   Map[] states = {
                new HashMap<>() {{
                    put(' ', 0);
                    put('s', 1);
                    put('d', 2);
                    put('.', 4);
                }}, // 0.
                new HashMap<>() {{
                    put('d', 2);
                    put('.', 4);
                }},                           // 1.
                new HashMap<>() {{
                    put('d', 2);
                    put('.', 3);
                    put('e', 5);
                    put(' ', 8);
                }}, // 2.
                new HashMap<>() {{
                    put('d', 3);
                    put('e', 5);
                    put(' ', 8);
                }},              // 3.
                new HashMap<>() {{
                    put('d', 3);
                }},                                        // 4.
                new HashMap<>() {{
                    put('s', 6);
                    put('d', 7);
                }},                           // 5.
                new HashMap<>() {{
                    put('d', 7);
                }},                                        // 6.
                new HashMap<>() {{
                    put('d', 7);
                    put(' ', 8);
                }},                           // 7.
                new HashMap<>() {{
                    put(' ', 8);
                }}                                         // 8.
        };

        int cur = 0;
        for (int i = 0; i < s.length(); i++) {
            char input = s.charAt(i);
            char trans = ' ';
            if (input <= '9' && input >= '0') {
                trans = 'd';
            } else if (input == ' ') {
                trans = ' ';
            } else if (input == '+' || input == '-') {
                trans = 's';
            } else if (input == '.') {
                trans = '.';
            } else if (input == 'e' || input == 'E') {
                trans = 'e';
            } else {
                trans = '?';
            }

//            若当前不能找到转换的状态,直接false
            if (!states[cur].containsKey(trans)) return false;
            else cur = (Integer) states[cur].get(trans);
        }

        return cur == 2 || cur == 3 || cur == 7 || cur == 8;
    }

等到19题弄懂了来发一波状态图的画法,立个flag

你可能感兴趣的:(数据结构和算法,字符串,状态机,算法,leetcode,java)