算法竞赛入门经典:第五章 基础题目选解 5.3 周期串

/*
周期串:
如果一个字符串可以由某个长度为k的字符串重复多次得到,我们说该串以k为周期。例如,abcabcabcabc是以3为周期(注意,它也以6和12为周期)。输入一个长度不
超过80的串,输出它的最小周期
输入:
HoHoHo
输出:2

思路:
关键找到切分点,从n/2长度算起吗,n/2-1长度,一直到1为止。这类似于希尔排序
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 1024


/*
从步长为2开始算起,若能整除,[若计算是周期,[直接输出;
                                            [步长累加,若步长超过一半,输出-1
                             [步长累加,若步长超过一半,输出-1

计算周期,0到步长内的每个数字,对每个字符与所有跳跃字符都相同
*/

/*
关键:
1周期串说白了就是 str[j] = str[j%i],注意步长应该从1开始,而不是从2开始,for(iStep = 1 ; iStep <= iLen/2 ; iStep++)
2 书上方法比我简单在:我是选取步长,将步长项全部比较结束。书上:一趟循环直接将所有步长项比结束
*/
int cycleStrLen_book(char* str)
{
	int iLen = strlen(str);
	int iStep;
	bool isCycle;
	for(iStep = 1 ; iStep <= iLen/2 ; iStep++)
	{
		isCycle = true;
		for(int j = 0;j < iLen; j++)
		{
			if(str[j] != str[j % iStep])
			{
				isCycle = false;
				break;
			}
		}
		if(isCycle)
		{
			break;
		}
	}
	return isCycle ? iStep : 0;
}

int cycleStrLen(char* str)
{
	int iLen = strlen(str);
	int iStep;
	bool isCycle; 
	//for(iStep = 2 ; iStep <= iLen/2;iStep++)//步长必须从1开始
	for(iStep = 1 ; iStep <= iLen/2 ; iStep++)
	{
		isCycle = true;
		if(iLen % iStep != 0)
		{
			isCycle = false;
			continue;
		}
		else
		{
			for(int i = 0 ; i < iStep;i++)//每个步长的起始位置
			{
				int j = i + iStep;
				while(j < iLen &&  str[j-iStep] == str[j])//判断跳跃字符是否都相等
				{
					j += iStep;
				}
				if(j < iLen)
				{
					isCycle = false;
					break;
				}
				if(isCycle)
				{
					break;
				}
			}
		}
		if(isCycle)
		{
			break;
		}
	}
	return isCycle ? iStep : -1;
}

int main(int argc,char* argv[])
{
	char str[MAXSIZE];
	scanf("%s",str);
	//printf("%d\n",cycleStrLen(str));
	printf("%d\n",cycleStrLen_book(str));
	system("pause");
	return 0;
}

你可能感兴趣的:(算法竞赛入门)