kmp是一种在线性时间内能处理两个字符串的包含关系的算法,例如求一个字符串里有没有另一个字符串,一个字符串里有几个另一个字符串(可重叠和不可重叠两种)。
贴个讲kmp的链接http://blog.csdn.net/yutianzuijin/article/details/11954939
模板
#include<stdio.h> #include<string.h> void makeNext(const char P[],int next[]) { int q,k; int m = strlen(P); next[0] = 0; for (q = 1,k = 0; q < m; ++q) { while(k > 0 && P[q] != P[k]) k = next[k-1]; if (P[q] == P[k]) { k++; } next[q] = k; } } int kmp(const char T[],const char P[],int next[]) { int n,m; int i,q; n = strlen(T); m = strlen(P); makeNext(P,next); for (i = 0,q = 0; i < n; ++i) { while(q > 0 && P[q] != T[i]) q = next[q-1]; if (P[q] == T[i]) { q++; } if (q == m) { printf("Pattern occurs with shift:%d ",(i-m+1)); } } } int main() { int i; int next[20]={0}; char T[] = "ababxbababcadfdsss"; char P[] = "abcdabd"; printf("%s ",T); printf("%s ",P ); // makeNext(P,next); kmp(T,P,next); for (i = 0; i < strlen(P); ++i) { printf("%d ",next[i]); } printf(" "); return 0; }
poj1961
题目大意,求这个字符串到i为止有多少个循环串;
int k = i-next[i];
if((i+1)%k == 0 && (i+1)!= k)
printf("%d %d
", i+1, (i+1)/k);
这是代码的主要部分,求next数组的部分大家都知道,我来说说这部分的正确性;
例如一个字符串的第99为指向第96位,也就是说后4-99位和前1-96位是匹配的,就是说94到96与97到99是是匹配的;
而且91-94与94-96是匹配的。。。。。。。。。。。
一直可以推到最前面,以上就是正确性啦~
代码
#include <iostream> #include <string.h> #include <map> #include <stdio.h> using namespace std; const int maxa =1000005; int next[maxa]; int vis[maxa]; int n; void init_kmp(char str[]) { memset(vis, 0, sizeof(vis)); next[0]=-1; for(int i=1;str[i]!=0;i++) { int j= next[i-1]; while(str[j+1]!=str[i]&&j>=0) j= next[j]; if(str[j+1] == str[i]) next[i] = j + 1; else next[i] = -1; } } int main(){ char str[maxa]; int d =1; while(scanf("%d", &n), n){ scanf("%s", str); printf("Test case #%d ", d++); init_kmp(str); for(int i = 0; i < n; i++){ int k = i-next[i]; if((i+1)%k == 0 && (i+1)!= k) printf("%d %d ", i+1, (i+1)/k); } printf(" "); } }