ACM - KMP题目小结 (更新中)

时间:2022-10-07 04:33:54

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

其它:

待补充。。。