poj2406--Power Strings+KMP求周期

先把结论摆出来:对于长为j的字符串str[1..j],next[j]=k,则令d=j-k;如果j%d==0,则这个字符串是一个

周期串,前d个字符是其最小的循环结,共包含j/d个循环节。

现在来解决两个问题:

1)前d个字符是其循环结

        下标  1   2  3  4  5  6  7  8 

      字符串 a   b  a  b  a  b  a  b

      next值 0   0  1  2  3  4  5  6

next[j]=k表示str[1...k]与str[j-k+1..j]是完全相等的;d=j-k所以str[1]=str[d+1]=str[j-k+1],

同样str[2]=str[d+2]=str[j-k+2]........str[d]=str[j-k+d].这样就证明了第1个循环节和第2个循环节是完全相等的。

于此类似由next数组的性质()我们也可以证明第3个循环节和第2个循环节也是相等的.........。最后我们可以证明所有的循环节都和第一个循环节相等,所以第一个循环节是字符串的循环节。

   我们可以用上面的字符串做一个演示:next[8]=6表示str[1...6]与str[3..5]完全相等;

d=8-6=2,共有8/2=4个循环节,第一个循环结为ab。然后由str[3]=str[1],str[4]=str[2]可知第二个循环节应为ab(实际上也是)然后由str[5]=str[3],str[6]=str[4]可知第三个循环节也为ab,然后由str[7]=str[5],str[8]=str[6]可知第四个循环结为ab。

所以我们可以看到第一个循环节确实是整个字符串的循环节。

2)前d个字符是其最小的循环结

   这一点比较容易证明,next[j]=k表示的是以第j个字符作为结尾的字符后缀与第一个字符开头的字符前缀最多有k个字符是想同的,即str[1---d]至多与str[j-k+1,j-k+d]相等,如果进一步减少d值next数组的性质就不能保证str[d]==str[j-k+d]成立,即前d个字符就不能作为一个循环节了。


代码如下


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

char str[1110000];
int next[1100000];

void Getnext()
{
    int j=0;
    int len=strlen(str+1);
    next[1]=0;
    for(int i=2;i<=len;i++)
    {
        while(j>0&&str[j+1]!=str[i])
            j=next[j];
        if(str[j+1]==str[i])
            j++;
        next[i]=j;
    }
}

int main()
{
    while(scanf("%s",str+1))
    {
        if(str[1]=='.')
            break;
        Getnext();
        int len=strlen(str+1);
        if(len%(len-next[len])==0)
        {
            printf("%d\n",len/(len-next[len]));
            continue;
        }
        printf("1\n");
    }
  return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值