Period HDU - 1358(KMP next 数组应用2)

For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A K , that is A concatenated K times, for some string A. Of course, we also want to know the period K.

Input

The input file consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S. The second line contains the string S. The input file ends with a line, having the number zero on it.

Output

For each test case, output “Test case #” and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case.

Sample Input

3
aaa
12
aabaabaabaab
0

Sample Output

Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4

对于KMP的知识,在前面的应用一样 ,这个题意就是给你一个字符串,让你找出某段字符串(由前面到后面)的周期串,例如aaa,就是个周期串 周期是1,重复了 3次,这个就可以,然后输出出现的位置和前面这段字符串重复的次数。但是前周期串一定要出现大于1次才可以满足条件输出。

对于这个问题,我们要考虑周期性,我们得拿出来next 数组这个神器来,解决这个问题。在之前已经说过,next 数组可以来找指定位置和状态的周期(很好用),所以我们主要用KMP 解决问题。

代码:
 

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<set>
#include<vector>
const int maxn=1000005;
using namespace std;
#include<map>
#include<string>
#include<string.h>
typedef long long ll;

int anext[maxn];

void getnext(string s)
{
	int i=0;
	int j=-1;
	anext[0]=-1;
	
	while(i<s.length())
	{
		if(j==-1||s[i]==s[j])
		{
			i++;
			j++;
			anext[i]=j;
		}
		else
			j=anext[j];
		
	}
	
}


int main()
{
	int n;
	int kase=0;
	
	char a[maxn];
	while(scanf("%d",&n)!=EOF)
	{
		if(n==0)
			break;
		memset(anext,0,sizeof(anext));
		scanf("%s",a);
		getnext(a);
		
		
		printf("Test case #%d\n",++kase);
		for(int i=2;i<=n;i++)	
			{
				if( i%(i-anext[i]) ==0 && i/(i-anext[i])!=1 )
					printf("%d %d\n",i,i/(i-anext[i]));
				
			}
			
		printf("\n");
	}
	
	
	
	
	return 0;
}

i-next[i],就是指定状态的周期性,这个题目的要求是前面必须是整除的周期串 就是i%(i-next[i]) 是整除的。就像 abcabc 在6位置处abc 重复两次。而abcab 就不是整除的,还需要再来一个字符c,才能满足条件。重复几次就是 i/(i-next[i]) ,恩,对。

猜你喜欢

转载自blog.csdn.net/tsam123/article/details/88356917