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;
}
posted @ 2020-01-30 20:25  ALKING1001  阅读(91)  评论(0编辑  收藏  举报