最近重温了KMP算法,顺便记录一下对KMP算法的理解,比较难懂的应该算是next数据的使用了,先说说自己的理解
首先要理解next数组的含义,假设有字符串, next[i] = n意味着 = ,意思就是在第i个字符串之前的字符串中(不包括第i)数量为n的后缀等于数量为n的前缀。那这个有什么用呢?
假设有字符串S和P,要在S中找到P,当比较P[i]和S[j]不相等时,如果是朴素算法,P回溯到0, S回溯到开始匹配的下一个位置(则i需要回溯到0(i=0)),从P[0]开始继续和S[j]继续比较,但在KMP算法里,P不需要回溯到0,回溯到next[i] = n(n i),S也不需要回溯,为什么要这样呢?因为比较P[i]和S[j]时(),假设 为 p , 为s,则p=s,根据next的含义,可知 = ,意思就是p的数量为n的前后缀相等,而p又等于s,所以p的前缀等于s的后缀。也就代表着当回溯的时候P的前n个字符串已经S[j]的之前的n个字符相等了,没必要把i赋值为0从P[0]开始进行比较了,也就是省去了再去比较这一段。例子我也懒得举了,至于next数组怎么算很多博客都有写,在这里我只想记录对next的理解。
def kmp_next(patterm):
next_arr = [0]
# prefix_index处在字符串前缀,
prefix_index = 0
i = 1
while i < len(patterm):
if patterm[i] == patterm[prefix_index]:
next_arr.append(prefix_index + 1)
prefix_index += 1
i +=1
else:
# 如果不相等,prefix_index回溯到它的上一个位置
if prefix_index >= 1:
prefix_index = next_arr[prefix_index - 1]
continue
# 如果prefix_index为0说明前缀和后缀没有相同的串
if prefix_index == 0:
i+=1
next_arr.append(0)
continue
return next_arr