主要关注题解中,将KMP算法转为动态规划的方法。在该方法中,字符串匹配的过程,被描述为确定转态转换的问题。利用动态规划,对KMP算法重新解读。
0. 前期知识:
chr(int) -> char
ord(char) -> int
1,分析:
在这个问题中,题解的作者认为主要存在两种状态转换的情况:其一,是当前txt的字符和pat的字符相同,所以状态推进1;其二,当前字符不同,则状态回滚。又,状态回滚又存在两种情况,完全回到初始位置和回到pat的某一位置。这里面,属于最后的情况最难处理。如果我们将pat的每个位置【0 》 len】作为一个状态标志,0位还未开始匹配,len为匹配结束,则显然,每次txt前进一个字符后,我们都需要考虑,状态转移的位置。所以,可以将该问题分为两个部分,首先确定状态转移过程,然后根据转移过程对字符串进行比对,找到具体解。
2,解
2.1 转态转移过程
要确定转移过程,首先,定义数组 dp[i][#], 表示在状态i遇到新字符#之后,转换后的状态值。重点是要理解状态回退的动态规划过程。我们可以引入后补状态,后补状态的位置“i”如何确定了。我们通过题主给的代码来解释(设为X):
hlen = len(haystack)
nlen = len(needle)
l = 256
dp = [[0 for _ in range(l)] for _ in range(nlen)] #dp[i][c], the state value of i-th state meet char c
X = 0 # hidden state
dp[0][ord(needle[0])] = 1 # start state
for i in range(1, nlen): # from start state
for j in range(l): # traverse all char value and only one jump on, others to call back
dp[i][j] = dp[X][j]
dp[i][ord(needle[i])] = i + 1
X = dp[X][ord(needle[i])]
*******python 数组的初始化只能选择题解中的,不然出现浅拷贝会出现意想不到的错误******
2.2 字符串比对过程
s = 0
for h in range(hlen):
s = dp[s][ord(haystack[h])]
if s == nlen:
return h - nlen + 1
3,代码
如上。
4, 总结
其实还是不太理解这个隐藏状态的问题,只能考虑X为每个回滚状态保留最优状态转移值。