[数据结构]KMP小结

来源:互联网 发布:视频语音聊天软件 编辑:程序博客网 时间:2024/05/29 08:30

KMP小结 

By Wine93 2013.9


1.学习链接



2.个人小结

(1).KMP在字符串中匹配中起着巨大作用,可以在O(n+m)内完成

(2).要充分理解next 数组,其求法和next数组的含义(最长后缀等于最长前缀),了解其用途,下面我就next数组在求字符串最小周期中的应用举例

(2.1).什么是字符串最小周期?

Ex:字符串ababab,最小周期为2,ab

Ex:字符串abcd,最小周期为4,abcd

(2.2)最小周期的一个性质

如果len%(len-next[len])==0,则该字符串的最小周期为len-next[len]

(2.3)性质的证明


欲证:若len%(len-next[len])==0, 则该字符串的最小周期为len-next[len]  (len表示该字符串长度)

        证:我们分2部分证

① 若len%(len-next[len])==0len-next[len]为字符串s的周期  

② 证明len-next[len]就是其最小周期

因为next数组的含义是最长后缀等于最长前缀,所以s[ 1……next[len] ]

s[next[len]+1……len ]是相等的,如上图,线段(1)和线段(2)相等

因为len%(len-next[len])==0,所以我们把线段(2)可以平均分成很多等份(图中假设为4),每份长度都为s1,线段(1)也可以分成同等份,如上图,根据next数组的定义,s1=s2,又因为s2=s3,s3=s4….所以依次类推可得s1=s2=s3=s4=s5=s6=s7=s8,所以,s1是字符串s的周期,所以①得证

len-next[len]不是其最小周期,也就是说存在更小的长度是字符串s的周期,也就是说next[len]要变大(也就是说最长前缀等于最长后缀的值要增大),而根据next数组的定义,next[len]就是已经是最大值(已经是最长前缀等于最长后缀),所以相互矛盾,所以②得证

综上所述如果len%(len-next[len])==0,则该字符串的最小周期为len-next[len] (len表示该字符串长度)


3.相关题

(1)循环节相关 

POJ 2406 Period 

HDU 3746 Cyclic Nacklace

CF 182D Common Divisors 

(2)Next数组

HDU 3336 Count the string

HDU 2594 Simpsons’ Hidden Talents

(3)KMP匹配

HDU 1711 Number Sequence 

CF 8A Train and Peter (string::find也可以)


4.KMP模板

# include<cstdio># include<cstring># include<vector># include<algorithm>using namespace std;# define VI vector<int># define N 200005int Next[N];void getnext(char *s){int i,j,len=strlen(s);Next[0]=j=-1;for(i=1;i<len;i++){while(j>=0&&s[j+1]!=s[i]) j=Next[j];if(s[j+1]==s[i]) j++;Next[i]=j;}}VI kmp(char *s,char *ch){int i,j,len=strlen(s),m=strlen(ch);VI ans;ans.clear();getnext(ch);j=-1;for(i=0;i<len;i++){while(j>=0&&ch[j+1]!=s[i]) j=Next[j];if(ch[j+1]==s[i]) j++;if(j+1==m) ans.push_back(i-m+1);}return ans;}


5.总结

总结:KMP的应用很大,一定要深入理解,尤其是next数组这对处理字符串匹配问题有着重大影响,AC自动机就是基于KMP来实现的.同时也要理解next数组的局限性(只能是后缀与前缀的对应关系),这对解题时的判断有着重要作用 

注:后缀数组可以解决KMP的一部分局限性




0 0