标签:将不 kmp code 总结 后缀 man 没有 line The
本文将不断加入例题,稍安勿躁,今天的总结争取9:30写完.
KMP,中文名字叫字符串匹配,用于解决一类字符串匹配问题.
先下一些定义:
首先我们先想一想\(nxt_i\)对于求解问题有怎样的帮助.
我们对于每一个\(t_i=s_1\)的位置都匹配一次,这样子复杂度为\(\Theta(n*m)\)的.
考虑在暴力匹配中其实我们不一定要重新匹配,因为你画一个图感性理解,发现如果匹配到了\(s\)的\(i\)前缀,到\(i+1\)失配,其实是可以从\(nxt_i\)重新开始匹配的.
这个时候\(nxt_i\)的好处就体现出来了,我们可以迅速再一次匹配.
void KMP(){
nxt[1]=0;int j=0;
for(int i=2;i<=n;i++){
while(j && s[i]!=s[j+1])j=nxt[j];
if(s[i]==s[j+1])j++;nxt[i]=j;
}
j=0;
for(int i=1;i<=m;i++){
while(j && s[j+1]!=t[i])j=nxt[j];
if(t[i]==s[j+1])j++;
if(j==n){ans.push_back(i-n+1);j=nxt[j];}
}
}
和\(KMP\)没有半毛钱关系,甚至和\(KMP\)的思想都没有半毛钱关系.
有两个字符串\(a\),\(b\),要求输出\(b\)与\(a\)的每一个后缀的最长公共前缀。
还是和往常通过一样的,从暴力入手。
枚举每一个\(a\)的后缀然后与\(b\)匹配,复杂度\(\Theta(n*m)\)的.
你当然可以\(Hash\),但是这与我们讨论的东西无关。
我们大致画一下图(==很重要==)发现显然之前匹配过的位置如果包含这个\(i\)后缀的第一个字符,那么可以从那一个最长匹配开始.
剩下的只需要不断像\(manacher\)一样匹配即可.
for(int i=1,l=0,mx=0;t[i];i++){
z[i]=(i<mx)?min(z[i-l],mx-i):0;
while(t[i+z[i]]==t[z[i]])z[i]++;
if(i+z[i]>mx){l=i;mx=i+z[i];}
}
大致就是这样子了,今天还是有点东西的.
标签:将不 kmp code 总结 后缀 man 没有 line The
原文地址:https://www.cnblogs.com/fexuile/p/11623418.html