KMP 算法最基本的应用场景是字符串的模式匹配,然而其应用远不止于此,在匹配字符串的过程中用到的一部分思想本身在一些场景中也可以得到应用,比如下面的这道求循环节的题。
题目大意就是给出一个字符串,然后求它的某个长度的前缀是否由循环节组成,若有则输出这个前缀的长度和循环节个数。
附上题目链接:[POJ 1961 -- Period]http://poj.org/problem?id=1961
本题只需要用到 next 数组。
对于一个字符串,我们构建了 next 数组之后,对于一个长度为 n 的前缀,如果它由循环节构成,那么它的 next 数组和它的长度之间有什么关系?
如果这个前缀由循环节构成,那么它的循环节一定是 s[1~n-m],因此只要看这个前缀的长度是否是 n-m 的倍数(大于1)。
#include <iostream> using namespace std; const int N = 1e6+10; char p[N]; int n,ne[N],cnt; int main(){ while(cin>>n,n){ cin>>(p+1); for(int i = 2,j = 0; i <= n ; i ++){ while(j && p[j+1] != p[i]) j = ne[j]; if(p[j+1] == p[i]) j++; ne[i] = j; } cout<<"Test case #"<<++cnt<<endl; for(int i = 2;i <= n ; i ++){ int k = i - ne[i]; if(i%k == 0 && i/k > 1)printf("%d %d\n",i,i/k); } puts(""); } return 0; }
同时附上一篇比较详细的讲解 kmp 的文章,以便日后复习。
https://www.cnblogs.com/yjiyjige/p/3263858.html