1. 程式人生 > >Poj1961 Poj2406 最短迴圈節

Poj1961 Poj2406 最短迴圈節

POJ1961:

先是用KMP“預處理"得出pre(程式中我習慣用p陣列)。

那麼關鍵就在於  (i+1)%(i-pre[i]) ==0  出現迴圈的判斷上。怎麼理解呢?這是就把陣列 str 分成  (i+1) / (i-pre[i]) 個部分,由pre性質可以看出 這些部分全部相等 ,也就是最小迴圈節,不太清楚可以在數軸上畫幾筆即可。這就是本題的關鍵所在。

#include "stdio.h"
int p[1000010],N;
char str[1000010];

void get_p(int n)
{
    int i,j=-1;
    p[0]=-1;
    for(i=1;i<n;i++)
    {
        while(j>-1 && str[i]!=str[j+1]) j=p[j];
        if(str[i] == str[j+1]) j++;
        p[i]=j;
    }
}

int main()
{
    int i,j,cas=1;
    while(scanf("%d",&N),N)
    {
        scanf("%s",str);
        get_p(N);
        printf("Test case #%d\n",cas++);
        for(i=1;i<N;i++)
        {
            if(p[i]!=-1 && (i+1)%(i-p[i])==0)
               printf("%d %d\n",i+1,(i+1)/(i-p[i]));
        }
        printf("\n");
    }
}

Poj2406 大同小異
#include "stdio.h"
#include "string.h"
int ans;
int p[1000010];
char str[1000010];

void get_p(int n)
{
    int i,j=-1;
    p[0]=-1;
    for(i=1;i<n;i++)
    {
        while(j>-1 && str[i]!=str[j+1]) j=p[j];
        if(str[i] == str[j+1]) j++;
        p[i]=j;
    }
}

int main()
{
    int i,j,k,N;
    while(1)
    {
        scanf("%s",str);
        N=strlen(str);
        if(N==1 && str[0]=='.') break;
        get_p(N);
        ans=1;
        if(N==1) printf("1\n");
        else{
            if(N%(N-1-p[N-1])==0) printf("%d\n",N/(N-1-p[N-1]));
            else printf("1\n");
        }
    }
}