Cyclic Nacklace hdu3746 kmp 最小循环节

  题意:给出一段字符串  求最少在最右边补上多少个字符使得形成循环串(单个字符不是循环串)

自己乱搞居然搞出来了。。。

想法是:  如果nex【len】为0  那么答案显然是补len

否则  答案为循环节的长度-nex【len】 小于0变0

写了一个假算法居然能过    。。。 ababca就错了

kmp重要性质:

重要的性质len-next[i]为此字符串的最小循环节(i为字符串的结尾),另外如果len%(len-next[i])==0,此字符串的最小周期就为len/(len-next[i]);

abcabcabc 为3

abcbca 为5

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define LL long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
#define N 100000+50
int nex[N];
int lenp,lens;
char p[N];
void getnext()
{
    lenp=strlen(p);
    nex[0]=-1;
    int k=-1,j=0;
    while(j<lenp)
    {
        if(k==-1||p[j]==p[k])
            nex[++j]=++k;
        else k=nex[k];
    }
}
int main()
{
    int n;
    RI(n);
    while(n--)
    {
        RS(p);
        getnext();
        if(nex[lenp]==0)
        {
            printf("%d
",lenp);
            continue;
        }
        int cnt=lenp-nex[lenp];//最小循环节
        
        printf("%d
",(cnt-lenp%cnt)==cnt?0:cnt-lenp%cnt);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/10685272.html