88888888y

导航

 

题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1457

题目思路:

思路就是预设子串的长度,从1开始,而后一段一段试

试到一个对不上的就打回

如果它完完整整的走了一圈

因为是从一开始然后一直往上加

所以第一个搜索到的就是最多的,最符合要求的

那就直接输出

注意一个魔鬼细节:当字符串长度无法整除预设子串长度时不可能出结果

借助这个判断,可以省下一大笔时间#include<bits/stdc++.h>

using namespace std;
#define ull unsigned long long
#define b 127//这个b必须是质数 
#define M 1000001
char a[M];//存字符串 
ull ahash[M],p[M];
//存字符串哈希值以及次方数 
int i,j,len,zlen;
//len是字符串长度,zlen是预设子串长度 
int main(){
	while(1){
		scanf("%s",a+1);
		if(a[1]=='.'){
			return 0;
		}
		//上为输入 
		len=strlen(a+1);// 
		p[0]=1;
		for(i=1;i<=len;++i){
			p[i]=p[i-1]*b;	
		}//次方数 
		ahash[0]=0;
		for(i=1;i<=len;++i){
			ahash[i]=ahash[i-1]*b+(ull)a[i];
		}//字符串每段哈希值 
		for(zlen=1;zlen<=len;++zlen){//预设子串,从1开始 
			if(len%zlen==0){//能整除,可能有解 
				for(j=0;j+zlen<=len;j+=zlen){//开算 
				 	if(ahash[j+zlen]-ahash[j]*p[zlen]!=ahash[zlen]){//算到个对不上的 
				 		break;//直接走 
					}	
				}
				if(j+zlen>len){//如果这个程序完整地走了一遍
				//证明这个方案可行 
					printf("%d\n",len/zlen);//发出来 
					break;
				} 
			}
		}
	}
	return 0;
}




题目总结:

基本公式 H[m]=(C[1]*b^(m-1)+C[2]*b^(m-2)+...+C[m]*1

对子串的计算

对于C'=C[1]C[2]...C[n]

H[C']=H[k+n]-H[k]*b^n

这是本题需要的知识储备

 

 

posted on 2022-05-02 11:27  88888888y  阅读(74)  评论(0)    收藏  举报