周期串(算法竞赛入门经典习题)

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

看见很多帖子都是用从1开始测周期的方法,分享一下我的思路,优点是只需要遍历一次字符串。

大体思路:因为每一个周期都是从第一个字符(str[0])开始的,所以直接找第二次出现 str[0] 的位置。若越界则说明最小周期就是字符串总长度。若找到,则两者间距离是当前最小周期,记作ans。从第二个出现str[0]的位置开始,向后遍历并同时与str[0],str[1]…str[ans-1]比较。 若有不同,更新ans 。若相同,检查后一位是否为str[0]。若是,则更新当前位置并重复上述比较过程 。若不是,则更新ans,并在寻找下一个str[0]的过程中更新ans。
代码:

#include 
#include 

int main(){
	char str[100];
	scanf("%s",str);
	int len=strlen(str);
	int ans=1;                            //最小周期至少是1 
	for(int i=1;i<len;){
		while(i<len && str[i]!=str[0]){   //寻找下一个str[0] 
			ans++; 
			i++;
		}
		if(i<len){                        //必有str[i]==str[0]
		    int count=0,j=i,start=0;
			for(;j<len;j++,start++){      //和当前最小周期逐个比较 
				if(str[j]!=str[start]) break;
				count++;
				if(count==ans) break;
			}
			if(count==ans){
				if(j==len-1) break;       //防止数组访问越界 
				if(str[j+1]!=str[0]){     //发现后一位不是str[0] 一定要及时更新最小周期 
					ans=j+2;
					i=j+2;
				}
				else i=j+1;
			}
			else{                         //count!=ans 
				if(j==len){
					ans=j;
					break;
				}
				ans=j+1;
				i=j+1;
			}
		}
	}
	printf("%d",ans);
}

你可能感兴趣的:(周期串(算法竞赛入门经典习题))