UVA1328 Period(KMP)

题意:给定一个长度为n的字符串,求它每个前缀的最短循环节

分析:KMP的失配函数有一个特点,i表示前i个字符,若i%(i-f[i])==0,则前i个字符,最短循环节的长度为i-f[i]。。

// File Name: 1328.cpp
// Author: zlbing
// Created Time: 2013/3/17 19:22:33

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,n) for(int i=0;i<n;i++)
#define REP1(i,n) for(int i=1;i<n+1;i++)
const int MAXN=1e6+10;
char ch[MAXN];
int f[MAXN];
void getFail(char *p,int *f){
    int m=strlen(p);
    f[0]=f[1]=0;
    for(int i=1;i<m;i++){
        int j=f[i];
        while(j&&p[i]!=p[j])j=f[j];
        f[i+1]=p[i]==p[j]?j+1:0;
    }
}
void find(char *T,char *p,int *f){
    int n=strlen(T);
    int m=strlen(p);
    getFail(p,f);
    int j=0;
    for(int i=0;i<n;i++){
        while(j&&p[j]!=T[i])j=f[j];
        if(p[j]==T[i])j++;
        if(j==m)printf("%d\n",i-m+1);
    }
}
int main(){
    int n;
    int cas=0;
    while(~scanf("%d",&n))
    {
        if(!n)break;
        scanf("%s",ch);
        printf("Test case #%d\n",++cas);
        getFail(ch,f);
        for(int i=2;i<=n;i++){
            if(f[i]&&i%(i-f[i])==0)printf("%d %d\n",i,i/(i-f[i]));
        }
        printf("\n");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/arbitrary/p/2964859.html