用DFA验证字符串中的数字
背景描述
有效数字(按顺序)可以分成以下几个部分:
- 一个 小数 或者 整数
- (可选)一个 ’e’ 或 ‘E’ ,后面跟着一个 整数
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-’)
- 下述格式之一:
- 至少一位数字,后面跟着一个点 ‘.’
- 至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
- 一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-’)
- 至少一位数字
部分有效数字列举如下:
["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分无效数字列举如下:
["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
提示
1 <= s.length <= 20
s 仅含英文字母(大写和小写),数字(0-9),加号 ‘+’ ,减号 ‘-’ ,或者点 ‘.’ 。
模拟
这种方式就是按照字符串的规律,写对对应的代码,来判断输入的字符串是否正确
模拟过程如下:
- 去掉开头、结尾的空格符(这步可以省略,按照提示字符串不包含空格)
- 如果是空串直接返回错误
- 判断开头的 + -,如果(+-)后面是空,则返回错误
- 处理数字和小数部分
- 如果小数点的个数 > 1,则返回错误
- 如果小数点个数 <= 1,判断数字数量是否 > 0
- 处理指数部分
- 这时候,还要判断下如果有指数e时,小数点>1 或 数字数量为0,则错误
- 处理 + - 部分
- 处理数字部分
- 判断剩余部分
代码如下:
|
|
也可以用正则来实现
|
|
DFA
这里需要用到编译原理的知识,用状态机来解析一个个的token
状态机有两种
- 非确定的有限自动机(Nondeterministic Finite Automaton,NFA)
- 确定的有限自动机(Deterministic Finite Automaton,DFA)
NFA占用内存小,但是效率差些,会出现回溯
DFA占用内存大,但是效率高,不会有回溯
我们来构造出DFA状态机(可以根据正则表达式构造),如下图:
上图中橙色节点是终止状态,也就当字符串遍历完后,位于这个状态下,就表示正确结束,返回true
如果是处于蓝色节点,就是中间状态,返回false
这里初始状态为0
,终止状态为2
、4
、7
如果输入的字符串是合法的,那么从0
开始出发,不管中间怎么转换,当字符串遍历结束后,最终一定会落到状态2
、4
、7
其中之一
之后,再根据状态机构造出跳转表,这个跳转表就等价于程序中用到的二维数组
跳转表如下:
state | +- | 0-9 | . | eE | other |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | -1 | -1 |
1 | -1 | 2 | 3 | -1 | -1 |
2 | -1 | 2 | 4 | 5 | -1 |
3 | -1 | 4 | -1 | -1 | -1 |
4 | -1 | 4 | -1 | 5 | -1 |
5 | 6 | 7 | -1 | -1 | -1 |
6 | -1 | 7 | -1 | -1 | -1 |
7 | -1 | 7 | -1 | -1 | -1 |
上述表格中的0 - 7
就对应了图中的各个状态
当在状态2
时,遇到.
就跳转到状态3
,于是在表格中对应的行和列中填3
当状态3
时,遇到0-9
就跳转到状态4
,于是在表格中对应的行和列中填4
将上述的表格保存为一个二维数组arr
,第一列的state
去掉
+-
对应第0
列、0-9
对应第1
、.
对应底2列
eE
对应底3
列,其他字符对应底4
列
然后根据当前状态,当前状态下的字符做跳转,比如:
- 当前状态
0
,字符为.
,也就是查找arr[0][3]
,跳转到状态3
- 当前状态
2
,字符为8
,查找arr[2][2]
,再次跳转到状态2
我们以-12.34E56
来说明上述的跳转表是如何工作的
-
对应第0列,arr[0][0] -> 状态 11
对应第1列,arr[1][1] -> 状态 22
对应第1列,arr[2][1] -> 状态 2.
对应第2列,arr[2][2] -> 状态 43
对应第1列,arr[4][1] -> 状态 44
对应第1列,arr[4][1] -> 状态 4E
对应第3列,arr[4][3] -> 状态 55
对应第1列,arr[5][1] -> 状态 76
对应第1列,arr[7][1] -> 状态 7- 字符串遍历结束,当前状态为
7
,是终止状态,匹配成功
代码如下:
|
|