Period HDU 1358 KMP next数组性质的应用

Period HDU 1358 KMP next数组性质的应用

原题链接

题意

题目的意思是给你一个字符串,判断这个字符串的前缀字符串中,哪些是周期串,输出这个前缀字符串的长度和这个前缀字符串中循环节的个数。

解题思路

思路参考:https://www.cnblogs.com/yym2013/p/3586495.html

这道题考察的是KMP算法中next数组的应用,必须理解透next[]数组代表的含义才能通过它解决这道题。
思路是先构造出 next[] 数组,下标为i,定义一个变量 j = i - next[i] 就是next数组下标和下标对应值的差,如果这个差能整除下标 i,即i%j==0 ,则说明下标i之前的字符串(周期性字符串长度为 i)一定可以由一个前缀周期性的表示出来,这个前缀的长度为刚才求得的那个差,即j,则这个前缀出现的次数为 i/j 。所以最后输出i和i/j即可。

注意:这里求next的算法不能是那种简化形式的。

这里需要特殊处理的是next[i] = 0或者next = -1要忽略。

代码实现

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
using namespace std;
const int MAXN=1e6+7;
char s[MAXN];
int  nx[MAXN], n;
void get_next()
{
    int j=0, k=-1, len=n; 
    nx[0]=-1;
    while(j<len)
    {
        if(k == -1 || s[j] == s[k])
        {
            j++; k++;
            nx[j] = k; 
        }
        else k = nx[k];
    }
}
int main()
{
    int count=1;
    while( scanf("%d", &n)  && n!=0)
    {
        int j=0;
        scanf("%s", s);
        get_next();
        printf("Test case #%d\n", count++);
        for(int i=2; i<=n; i++)
        {
            if(nx[i] <= 0)
                continue;
            j = i - nx[i];
            if(i % j == 0)
                printf("%d %d\n", i, i/j);
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/alking1001/p/12243767.html