poj 2046 Power Strings KMP

题目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;
}
原文地址:https://www.cnblogs.com/0803yijia/p/2601002.html