KMP算法题型大致有两类,一类是next数组的应用,一类是匹配问题。
next数组大多数是求字符串周期,或者是与前缀后缀有关,也可以应用在DP中。需要对next数组有一定理解才能做得出。
next数组有一些性质。L为字符串长度。
如,L%(L-next[L])==0,说明字符串S[0,L-next[L]]是重复子串。
周期串/求循环节:
HDU 1358 Period
http://acm.hdu.edu.cn/showproblem.php?pid=1358
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define MAXN 1000005 using namespace std; int next[MAXN]; char str[MAXN]; void getFail() { ; str[i]; ++i) { int j=next[i]; while(j&&str[i]!=str[j]) j=next[j]; next[i+]=(str[i]==str[j])?j+:; } } int main() { ; while(scanf("%d",&n)&&n) { scanf("%s",str); getFail(); printf("Test case #%d\n",++kase); ; i<=n; ++i) { int k=i-next[i]; &&i/k!=) printf("%d %d\n",i,i/k); } printf("\n"); } ; }
HDU 3746 Cyclic Nacklace
http://acm.hdu.edu.cn/showproblem.php?pid=3746
POJ 2406 Power Strings
http://poj.org/problem?id=2406
#include<iostream> #include<cstring> #include<cstdio> using namespace std; ]; ]; void getFail() { ; str[i]; ++i) { int j=next[i]; while(j&&str[i]!=str[j]) j=next[j]; next[i+]=(str[i]==str[j])?j+:; } } int main() { ]!='.') { getFail(); int L=strlen(str); int p=L-next[L]; ) printf("%d\n",L/p); ); } ; }
前缀/后缀:
POJ 2752 Seek the Name, Seek the Fame
http://poj.org/problem?id=2752
HDU 2594 Simpsons’ Hidden Talents
http://acm.hdu.edu.cn/showproblem.php?pid=2594
HDU 4300 Clairewd’s message
http://acm.hdu.edu.cn/showproblem.php?pid=4300
#include<iostream> #include<vector> #include<cmath> #include<map> #include<string> #include<cstring> using namespace std; ],lenb; map<char,char> has; string str,a,b,s; //char has[30]; void getFail() { ; i<str.size(); ++i) { int j=next[i]; while(j&&str[i]!=str[j]) j=next[j]; next[i+]=(str[i]==str[j])?j+:; } } string ans; void Find(int p) { while(!(next[p]<=(lenb-next[p]))) p=next[p]; ans.clear(); ; i<a.size(); ++i) ans+=a[i]; for(int i=next[p]; i<lenb-next[p]; ++i) ans+=b[i]; } int main() { int T; cin>>T; while(T--) { cin>>s>>a; b.clear(); has.clear(); ; i<s.size(); ++i) has[s[i]]=i+'a'; ; i<a.size(); ++i) b+=has[a[i]]; str=b+a; lenb=b.size(); getFail(); Find(str.size()); cout<<ans<<endl; } ; }
其他:
HDU 3336 Count the string
http://acm.hdu.edu.cn/showproblem.php?pid=3336
字符串匹配问题主要有匹配单个模版串,寻找公共子串。难的是它的应用。
单串匹配:问一个字符串在另一个字符串里出现了多少次。
HDU 2087 剪花布条 (不能重叠)
http://acm.hdu.edu.cn/showproblem.php?pid=2087
POJ 3461 Oulipo (可以重叠)
http://poj.org/problem?id=3461
二维匹配:
POJ 2185 Milking Grid
http://poj.org/problem?id=2185
需要降维后再使用KMP。
公共子串:此类问题大多数是KMP+暴力枚举
POJ 3080 Blue Jeans
http://poj.org/problem?id=3080
POJ 3450 Corporate Identity
http://poj.org/problem?id=3450
其它:
待补充。。。