Period 【HDU - 1358】【KMP求周期】

学习KMP算法可以参阅这篇文章,不懂的可以在线回答

题目链接


题意:

我们想知道一串字符中的前缀中有多少最大周期数,例如“aaa”中,前两个“aa”最小周期长度为“a”,所以周期长度为2,前三个“aaa”的最小周期也是“a”所以周期长度为3;再如“aabaabaabaab”中前6个“aabaab”的最小周期长度为“aab”,所以周期为2......。


  这道题就是要理解KMP的运行过程才能好做些,我们了解到next[]数组的遍历规律,恰好就是前缀的关系,譬如“aabaab”的前缀next[]数组的存储是这样的{0, 1, 0, 1, 2, 3},对于前两个“aa”,它们的规律是第二个“a”恰是在第一个基础上的,证明前面恰好一个与其相等且呈周期性,那么再举例到“aabaab”,我们看到第五个字符“a”,他的next[]值为“2”,但是以它为终止的话却不能恰好构成一个完整的周期而我们剪去它的值就是残余数,是5(第5个)-next[5](前面的周期关系)=5-2=3,而5%3!=0,所以不构成周期,而第六个字符以类似规律可以。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>    
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=1e6+5;
char a[maxN];
int N, nex[maxN];
void cal_nex()
{
    nex[0] = nex[1] = 0;
    int k = 0;
    for(int i=2; i<=N; i++)
    {
        while(k>0 && a[k+1]!=a[i])
        {
            k = nex[k];
        }
        if(a[k+1] == a[i]) k++;
        nex[i] = k;
    }
}
int main()
{
    int Cas=0;
    while(scanf("%d", &N) && N)
    {
        getchar();
        scanf("%s", a+1);
        cal_nex();
        printf("Test case #%d\n", ++Cas);
        for(int i=2; i<=N; i++)
        {
            int tmp = i - nex[i];
            if(i>tmp && i%tmp==0) printf("%d %d\n", i, i/tmp);
        }
        printf("\n");
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值