uvalive 3026 Period KMP(失配函数)

题意:

给定一个长度为n的字符串,求它每个前缀的最短循环节。即对于i长前缀,存在一个k(k>1)使得,所有[i/k*(j-1),i/k*j]区间的字符串都相等,(1<=j<=k,i%k==0)。

题解:

我们用到KMP中求失配函数f[i]的方法。f[i]表示状态i失配时转移到得新状态,f[0]=0。我们可以证明当f[i]>0且i%(i-f[i])==0时,i长前缀存在i/(i-f[i])长的循环节。证明方法需要通过f[i]的性质来证明,[0,f[i]]和[i-f[i],f[i]]是相等的,当i%(i-f[i])==0时,我们可以每(i-f[i])分段,分成ci,由于[0,f[i]]和[i-f[i],f[i]]是相等的,所以ci=ci+1,因而上述的求解方法是正确的(当i%(i-f[i])!=0时也可以用相同方式证明不成立)。




代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

const int maxn=1e6+10;
char a[maxn];
int f[maxn];
int main()
{
    int n,tt=0;
    while(scanf("%d",&n)!=EOF)
    {
        int i,j,k;
        if(n==0)break;
        scanf("%s",a);
        f[0]=f[1]=0;
        for(i=1;i0&&i%(i-f[i])==0)printf("%d %d\n",i,i/(i-f[i]));
        }
        printf("\n");
    }
    return 0;
}



你可能感兴趣的:(KMP)