KMP
- 当ABABAAB和ABAA进行匹配
- ABAB 和ABAA 不匹配的时候,但ABA匹配
- 找ABA的最长前缀,直接将匹配子串的头 放到刚刚匹配到的地方
- 最长前缀存放在next数组中,next[j]可以通过next[j-1]获得 :动态规划
- next[i-1]=j:
- 当v==u:next[i]=next[i-1]+1 =j+1
- 当v!=u:j=next[j] (往前跳)
文本串指针不动,一直动的是模式串指针
案例–求next数组
模式串索引 0 1 2 3 4 5 6 7 8 9 10 11 模式串s a e a d a e a d a e a e next[] -1 -1 0 -1 0 1 2 3 4 5 6 1
- 默认next[0]=-1 j=-1
- e和s[j+1]比 :e和s[-1+1]=a比:不匹配,j=-1
- a和s[j+1]比:a==a : j=j+1 ,j=0
- d和s[j+1]比:d!=e :往前跳j=next[j] j=-1 :
- d和s[j+1]比:d!=a :j=-1
- a和s[j+1]比:a==a:j=0
- e和s[j+1]比:e==e:j=1
- a和s[j+1]比:a==a:j=2
- d和s[j+1]比:d==d:j=3
- a和s[j+1]比:a==a:j=4
- e和s[j+1]比:e==e:j=5
- a和s[j+1]比:a==a:j=6
- e和s[j+1]比:e!=d:往前跳,j=next[j],j=next[6],j=2
- e和s[j+1]比:e!=d :往前跳,j=next[j],j=next[2],j=0
- e和s[j+1]比:e==e :j+1
//获取next数组
int *getNext(const char *t){
int tlen=strlen(t);
int *next=(int *)malloc(sizeof(int)*tlen);
next[0]=-1;
int j=-1; //j=next[i-1]
for(int i=1;t[i];i++){ //遍历模式串的每一位
while(j!=-1 && t[i]!=t[j+1]) //当uv不相等的时候,j才往前跳
{
j=next[j];
}
//相等的时候就j+1
if(t[i]==t[j+1])j+=1;
next[i]=j; //然后将j赋给next[i],完成当前模式串第i位的next赋值
}
return next;
}
int KMP(const char *s,const char *t){
//先获得一个next数组
int *next=getNext(t);
int j=-1,tlen=strlen(t);
for(int i=0;s[i];i++){
while(j!=-1 && s[i]!=t[j+1]) //当文本串不等于模式串的t[j+1]个字符的时候
//调整j的位置,在next数组里面(往前跳)
{
j=next[j];
}
if(s[i]==t[j+1])j+=1; //相等的时候,j+=1
if(t[j+1]==0){//全都匹配上了,返回起始位置
{
return i-tlen+1;
}
}
}
return -1;
}
#!/usr/bin/python3
# _*_ coding: utf-8 _*_
#
# Copyright (C) 2024 - 2024 Cry, Inc. All Rights Reserved
#
# @Time : 2024/4/13 1:44
# @Author : Cry
# @File : KMP.py
# @IDE : PyCharm
def getNext(s):
slen=len(s)
next=list(range(slen+1))
next[0]=-1 # [-1,0,1,2,3,1,2] 第0位为-1
j=-1
i=1
for c in s: #遍历模式串的每一位
while(j!=-1 and c!=s[j+1]): # uv不相等,往前跳
j=next[j] #一直往前跳,直到相等为止
if(c==s[j+1]): #uv相等,j+1
j+=1
next[i]=j
i+=1
return next
def kmp(s,t):
next=getNext(t) #获得模式串的next数组
print(next)
j=-1
tlen=len(t)
for i in range(len(s)):
while j!=-1 and s[i]!=t[j+1]:
j=next[j]
if s[i]==t[j+1]:
j+=1
if j+1==tlen: #模式子串都匹配完成,输出起始位置
return i-tlen+1
return -1
print(kmp("abcdefghijk","lmn"))