hdu 3746 Cyclic Nacklace(KMP)

题意:给出一个串,问最少在串末尾添加几个字符,才能让串中出现循环。


思路:这题要很好的理解next数组的性质才行,构造完next数组以后,有这样一个性质:字符串的最小循环节的长度为len-next[len],如果len%(len-next[len])==0,那么字符串的最小周期为len/(len-next[len]) 。

           这是如何得到的呢,先来看下下面的图:

首先是①图,假设上面的是给定的串,求完next数组后,next[len]=6,如果发生转移,那么就会变成下面那个样子,这时候观察一下可以发现,原来绿色的abc这个串对应到蓝色的abc这个串上,也就是说这两个串相等,同时,蓝色的串又对应到红色的串上,这是可以一直往下递推的,因此,我们可以得出一个结论,那就是abc这个串是一个循环节。也就是说循环的串是S[next[len]+1……len]。

然后是②图,同样,上面是给定的串,下面是转移之后的状态,还是以上面的思路来看的话,bbbabc是一个循环节,然而,bbb却没用可以对应的字符,也就是说上面的串由于长度不够,因此无法构成循环,这样就比较明白了,如果len%(len-next[len])==0,那么循环节是恰好能形成循环的,否则不行。

这一道题也是一样的道理,要求的就是循环缺少的字符的个数,也就是相当于②图在bbb的位置的串的个数。


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
char str[maxn];
int next[maxn];
void getnext(int n)
{
    next[0]=next[1]=0;
    for(int i=1;i<n;++i)
    {
        int j=next[i];
        while(j&&str[i]!=str[j]) j=next[j];
        next[i+1]=(str[i]==str[j])?j+1:0;
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        int n=strlen(str);
        getnext(n);
        int ans=n-next[n];
        if(ans==n) ans=n;
        else if(n%ans==0) ans=0;
        else ans=ans-n%ans;
        printf("%d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值