KMP模式匹配算法
程序员文章站
2022-04-01 12:42:04
...
KMP算法主要解决的问题是如何较为高效地在主串中寻找指定的字串。这种算法可以大大避免朴素匹配中出现的重复遍历的情况。算法的实质是利用字子串自身所具有的一些特殊性质,得到一个函数返回函数Next,从而通过函数Next来避免大量重复遍历的情况。
下面先给出函数Next的定义:
对于字符串T(也可看成是字符列表)
定义的意义:设主串为,子串为,假设比较进行到了处,且:
1.当时,,此时需要进行的比较为与;
2.当不为空时,
按照定义取,因为对于已经同比较过且相等,又因为,这意味着已经得到,故需要比较的只有与,故此时的意义是避免了对做无谓的比较,让子串与主串的比较直接从子串的第k处开始。
3.当为其他情况时,直接从头开始比较。
Next代码
def get_Next(T):
j=0
Next=[-1]
for j in range(1,len(T)):
K=[k for k in range(2,j+1) if T[0:k-1]==T[j-k+1:j] and k-1>0]
if K:Next.append(max(K)-1)
else:Next.append(0)
return Next
完整代码
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 15 10:14:32 2019
@author: Administrator
"""
def get_Next(T):
j=0
Next=[-1]
for j in range(1,len(T)):
K=[k for k in range(1,j) if T[0:k]==T[j-k:j] and k>0]
if K:Next.append(max(K))
else:Next.append(0)
return Next
def Index_KMP(S,T,pos=0): #S:主串,T:子串,pos:在主串中开始搜寻的位置
j=0
i=pos
Next=get_Next(T)
while (i<len(S) and j<len(T)):
if j==-1 or S[i]==T[j]:
#即在上一次比较中发现子串T中第一个字母便与S[i]不同,或者是S[i]==t[j],则主串和子串的指标i,j均往后移1个位置
i+=1
j+=1
else:
#即j!=-1且S[i]!=T[j]
j=Next[j]
if j==len(T):
#如果对于T比较完成,则返回主串中对应位置的开头
return i-len(T)
else:
return -1
S='dasdfhaskaslsfkjhfweiu'
T='askasls'
Index_KMP(S,T,pos=0)
关于Next函数的改进
改进的实质:在S[i]!=T[j]时,在计算的值的同时,如果位字符与它值所指向的位字符相等,则该位的就指向位的值,这是因为位字符如果通过回到前面的字符位置后,接下来要进行比较的就是与,而我们已经比较得到,故若,则也有,故需要再次通过返回,即返回至;如果不相等,则位的值就是它自己位的值。
Nextval代码
def get_Nextval(T):
j=0
Nextval=[-1]
for j in range(1,len(T)):
K=[k for k in range(1,j) if T[0:k]==T[j-k:j] and k>0]
if K:
if T[max(K)]==T[j]:Nextval.append(Nextval[max(K)])
else:Nextval.append(max(K))
else:
if T[j]==T[0]:Nextval.append(-1)
else:Nextval.append(0)
return Nextval