10035. 「一本通 2.1 练习 1」Power Strings
AC代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000010;
int b=31;
ULL sum[N],power[N];
int len[N];
char s1[N];
void init()
{
int i;power[0]=1;
for(i=1;i<N;i++)
power[i]=power[i-1]*b;
}
int Hash()
{
int i,j,k,l,z;
ULL s,ss;
l=strlen(s1+1);z=1;
for(i=1;i<=l;i++)
if(l%i==0)
len[z++]=i;//子字符串可能的长度
for(i=1;i<=l;i++)
sum[i]=sum[i-1]*b+(ULL)(s1[i]-'A'+1);
for(i=1;i<z;i++)
{
for(k=0;k<=l-len[i];k+=len[i])//子字符串首字符位置 -1 首位置是k+1
{
s=sum[k+len[i]]-sum[k]*power[len[i]];
if(ss==s&&k!=0)continue;//和上一个相同长度的子字符串的哈希值相同的直接跳过
for(j=0;j<=l-len[i];j+=len[i])//子字符串首字符位置 -1 首位置是k+1
if(s!=sum[j+len[i]]-sum[j]*power[len[i]])
break;
if(j==l)//子字符串重复且连接,因为是从一个长度的子字符串开始,所以只要找到就是最大的值
return l/len[i];
ss=s;//记录处理过的子字符串的哈希值,留到下次判断用
}
}
return 1;//因为都能从上面的出口出去这个return无所谓,但是交到oj上会有警告性错误
}
int main()
{
init();
while(scanf("%s",s1+1),s1[1]!='.')
printf("%d\n",Hash());
return 0;
}
第一次思路:
最后一个样例超时
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000010;
int b=31;
ULL sum[N],power[N];
int len[N];
char s1[N];
void init()
{
int i;power[0]=1;
for(i=1;i<N;i++)
power[i]=power[i-1]*b;
}
int Hash()
{
int maxn,ans,i,j,k,l,kk,z;
ULL s;
l=strlen(s1+1);maxn=0;z=1;
for(i=1;i<=l;i++)
if(l%i==0)
len[z++]=i;
for(i=1;i<=l;i++)
sum[i]=sum[i-1]*b+(ULL)(s1[i]-'A'+1);
for(i=1;i<z;i++)
{
for(k=0;k<=l-len[i];k+=len[i])
{
s=sum[k+len[i]]-sum[k]*power[len[i]];
for(j=0;j<=l-len[i];j+=len[i])
if(s!=sum[j+len[i]]-sum[j]*power[len[i]])
break;
if(j==l)
return l/len[i];
}
}
}
int main()
{
init();
while(scanf("%s",s1+1),s1[1]!='.')
printf("%d\n",Hash());
return 0;
}
第二次思路:
本想着标记过的跳过,优化一下
结果后四个样例超时
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000010;
map<string,int> mmm;
int b=31;
ULL sum[N],power[N];
int len[N];
char s1[N];
string str;
void init()
{
int i;power[0]=1;
for(i=1;i<N;i++)
power[i]=power[i-1]*b;
}
int Hash()
{
//****************************
mmm.clear();//注意清空
//****************************
int i,j,k,l,z;
ULL s;
l=strlen(s1+1);z=1;
for(i=1;i<=l;i++)
if(l%i==0)
len[z++]=i;
for(i=1;i<=l;i++)
sum[i]=sum[i-1]*b+(ULL)(s1[i]-'A'+1);
for(i=1;i<z;i++)
{
for(k=0;k<=l-len[i];k+=len[i])
{
s=sum[k+len[i]]-sum[k]*power[len[i]];
//****************************
if(mmm[str])continue;
str.assign(s1+1,k,len[i]);
mmm[str]=1;
str.clear();//注意清空
//****************************
for(j=0;j<=l-len[i];j+=len[i])
if(s!=sum[j+len[i]]-sum[j]*power[len[i]])
break;
if(j==l)
return l/len[i];
}
}
}
int main()
{
init();
while(scanf("%s",s1+1),s1[1]!='.')
printf("%d\n",Hash());
return 0;
}