KMP之Power Strings

NEFU 2131 字符串乘方

模拟过程:
这道题十分巧妙地运用了next数组的性质;
s [ 0... n e x t [ i ] ] = s [ i − n e x t [ i ] + 1... i ] s[0...next[i]]=s[i-next[i]+1...i] s[0...next[i]]=s[inext[i]+1...i]

若s字符串存在重复,则如图所示
在这里插入图片描述
next数组的构建:

  1. n e x t [ i ] next[i] next[i]数组就是描述:最长当前 1 − i 1-i 1i长度的字符串的最长前缀和后缀的长度。
  2. 如果存在重复单元,则 l e n − n e x t [ l e n ] len-next[len] lennext[len]就是最短的循环串。
  3. l e n m o d    ( l e n − n e x t [ l e n ] ) = 0 len\mod(len-next[len])=0 lenmod(lennext[len])=0的话,就会存在循环节。则 l e n / ( l e n − n e x t [ l e n ] ) len/(len-next[len]) len/(lennext[len])就是答案。

举例:

字符串:    a b c a b c a b c
next数组:  0 0 0 1 2 3 4 5 6

字符串:    a b c d a b c e
next数组:  0 0 0 0 1 2 3 0

字符串:    a a a a a a a b
next数组:  0 1 2 3 4 5 6 0

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int maxn = 1e6 + 5;
char s[maxn];
int Next[maxn];
int main()
{
    while (~scanf("%s", s))
    {
        if (s[0] == '.')
            break;
        int len = strlen(s);
        memset(Next, 0, sizeof(Next));
        int i = 0, j = -1;
        Next[0] = -1;   //s[i]代表后缀,s[j]代表前缀
        while (i < len) //next定义为最长的前缀==后缀
        {
            if (j == -1 || s[i] == s[j])
            {
                i++;
                j++;
                Next[i] = j;
            }
            else
                j = Next[j];
        }                                           
        if (len % (len - Next[len]) == 0)            //如果第i-1位为结尾的循环必定有 i % (i - Next[i]) == 0
            printf("%d\n", len / (len - Next[len])); //0~i-1共有i个字符,i / (i - Next[i])就是循环次数。
        else
            printf("1\n");
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值