返回
直击本质,正则表达式匹配算法精髓解读
闲谈
2023-12-05 16:34:27
Leetcode算法刷题 10.正则表达式匹配
前言
今天做了一道动态规划题目,Leetcode上的正则表达式匹配,分享下题解。
题目连接:10. 正则表达式匹配
思路
本题一看就是一个动态规划,或者递归解法,不过递归就太耗时了。
整体思路如下:
-
首先将正则表达式转换成一个NFA(Nondeterministic Finite Automaton,非确定性有限自动机)。
-
然后将字符串转换成一个DFA(Deterministic Finite Automaton,确定性有限自动机)。
-
最后再用NFA和DFA进行匹配,就可以得到结果。
实现细节
1. 正则表达式转NFA
正则表达式转NFA的规则如下:
.
匹配任何字符。*
匹配0个或多个前面的字符。+
匹配1个或多个前面的字符。?
匹配0个或1个前面的字符。[]
匹配方括号中的任意一个字符。()
将括号内的正则表达式作为一个整体。
例如,正则表达式.ab*c
可以转换成NFA如下:
ε
/ \
/ \
a b
/ \ / \
ε ε ε c
2. 字符串转DFA
字符串转DFA的规则如下:
- 将字符串的第一个字符作为DFA的起始状态。
- 将字符串的最后一个字符作为DFA的终止状态。
- 将字符串中间的每个字符作为DFA的一个状态。
- 将每个状态的转移函数设置为:如果该状态的字符与下一个字符匹配,则转移到下一个状态;否则,转移到终止状态。
例如,字符串"abc"可以转换成DFA如下:
a -> b -> c -> $
3. NFA和DFA匹配
NFA和DFA的匹配规则如下:
- 如果NFA的起始状态和DFA的起始状态匹配,则将NFA的起始状态和DFA的起始状态都标记为已访问。
- 如果NFA的某个状态和DFA的某个状态都标记为已访问,并且这两个状态的转移函数相同,则将这两个状态都标记为已访问。
- 如果NFA的某个状态和DFA的某个状态都标记为已访问,并且这两个状态的转移函数不同,则将这两个状态都标记为未访问。
- 如果NFA的所有状态都标记为已访问,则匹配成功;否则,匹配失败。
例如,NFA和DFA如下:
ε
/ \
/ \
a b
/ \ / \
ε ε ε c
\ / \
\ \
b $
字符串"abc"与NFA和DFA匹配的过程如下:
- 将NFA的起始状态和DFA的起始状态都标记为已访问。
- 将NFA的a状态和DFA的a状态都标记为已访问。
- 将NFA的b状态和DFA的b状态都标记为已访问。
- 将NFA的c状态和DFA的c状态都标记为已访问。
- 将NFA的状态和DFA的状态都标记为已访问。
因此,NFA和DFA匹配成功。
结语
正则表达式匹配算法是一道经典的动态规划题目,也是Leetcode上的一道热门题目。掌握正则表达式匹配算法的精髓,可以帮助你解决更多类似的题目,提升你的算法能力。