HDU 3746 (KMP求最小循环节) Cyclic Nacklace

题意:

给出一个字符串,要求在后面添加最少的字符是的新串是循环的,且至少有两个循环节。输出最少需要添加字符的个数。

分析:

假设所给字符串为p[0...l-1],其长度为l

有这样一个结论:

这个串的最小循环节为 l - next[l]

感觉自己想得不是特别透彻,所以把别人的博客贴上来吧。

里面有个小错误就是:next[i]的值应该为j-k

 

对于这种情况还可以这样想:

|←②→|←④→|

------------------------

------------------------

|←①→|←③→|

这是同一个字符串

其中红色代表相同的前缀和后缀

前面那段黄的(①段)等于上面对应等长的红的部分(②段),因为前缀和后缀相同,所以②段和③段相同,③段又和正上方的④段相同,以此类推。

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;



const int maxn = 100000 + 10;

char p[maxn];

int next[maxn];



void get_next(char* p, int l)

{

	int k = -1, j = 0;

	next[0] = -1;

	while(j < l)

	{

		if(k == -1 || p[k] == p[j])

		{

			k++;

			j++;

			next[j] = k;

		}

		else k = next[k];

	}

}



int main(void)

{

	//freopen("3746in.txt", "r", stdin);

	int T;

	scanf("%d", &T);

	while(T--)

	{

		memset(next, 0, sizeof(next));

		scanf("%s", p);

		int l = strlen(p);

		get_next(p, l);

		if(next[l] == 0)

		{

			printf("%d\n", l);

			continue;

		}

		int cir = l - next[l];

		if(l % cir == 0)

		{

			puts("0");

			continue;

		} 

		printf("%d\n", cir - (l % cir));

	}

	

	return 0;

}

 

你可能感兴趣的:(HDU)