题目http://poj.org/problem?id=2406
/* 一开始不大理解,写了个笨方法,就是从s[0]开始找。因为一定是从s[0]开始的子串只要len==len1*count 就直接输出,后来发现tle /* memset(s1,0,sizeof(s1)); for(i = 0;i < len;i++) { s1[i] = s2[i]; predeal(s1); for(i = 0;s2[i] != '\0';i++) printf("%d ",pre[i]); puts(""); int count = 0,len1; len1 = strlen(s1); count = kmp(s1,s2); if(count*len1 == len) { printf("%d\n",count); break; } }*/ 然后又发现其实pre数组就能够很好的利用,pre[len-1]储存的是上一个周期子串结束的地方所以len%(len-pre[len-1])直接就可以判断是不是。但是要注意如果他本省市自己的最小子串的话,要另加判断~也就是else printf("1\n"); */ #include <iostream> #include <stdio.h> #include <string.h> using namespace std; int pre[1000005]; void predeal(char s[]) { int len,i,j; len = strlen(s); pre[0] = -1; j = -1; for(i = 1;i < len;i++) { while(j > -1 && s[j+1] != s[i]) j = pre[j]; if(s[j+1] == s[i]) j++; pre[i] = j; } } int kmp(char s1[],char s2[]) { int len1,len2,i,j,num; len1 = strlen(s1); len2 = strlen(s2); num = 0; for(i = 0,j = -1;i < len2;i++) { while(j > -1 && s1[j+1] != s2[i]) j = pre[j]; if(s1[j+1] == s2[i]) j++; if(j == len1-1) j = pre[j],num++; } return num; } int main() { int n,i,j; char s2[1000005]; while(scanf("%s",s2) != EOF) { if(strcmp(s2,".") == 0) { break; } int len = strlen(s2); predeal(s2); printf("%d",pre[len-1]); if(len%(len-pre[len-1]-1) == 0) { printf("%d\n",len/(len-pre[len-1]-1)); } else printf("1\n"); } return 0; }