题目来源:中山纪念中学
题目描述:
俗话说“好命不如好名”,小h准备给他的宠物狗起个新的名字,于是他把一些英文的名字全抄下来了,写成一行长长的字符串,小h觉得一个名字如果是好名字,那么这个名字在这个串中既是前缀,又是后缀,即是这个名字从前面开始可以匹配,从后面开始也可以匹配,例如abc在 abcddabc中既是前缀,也是后缀,而ab就不是,可是长达4*10^5的字符让小h几乎昏过去了,为了给自己的小狗起个好名字,小h向你求救,并且他要求要将所有的好名字的长度都输出来。
输入:
一行,要处理的字符串(都是小写字母)。
输出:
一行若干个数字,从小到大输出,表示好名字的长度。
输入样例:
abcddabc
输出样例:
3 8
思路:哈希
很多人用kmp来写,可是我觉得前缀哈希更好理解一点,用ha[i]来表示前i个字母的哈希前缀和,设现在枚举到前i个字母,当ha[i]=ha[n-i]*power[i]时,二者相等,直接输出i就可
单哈希,不用取模也可以过
AC代码:
#include<bits/stdc++.h>
#define N 401000
using namespace std;
typedef unsigned long long ULL;
char a[N];
ULL n,power[N],ha[N],b=127;
int main()
{
scanf("%s",a+1);
n=strlen(a+1);
power[0]=1;
for (int i=1;i<=n;i++) power[i]=power[i-1]*b;
for (int i=1;i<=n;i++) ha[i]=ha[i-1]*b+(ULL)(a[i]-'A'+1);
for (int i=1;i<=n;++i)
{
ULL ha2=ha[n]-ha[n-i]*power[i];
if (ha[i]==ha2&&ha2!=0) printf("%d ",i);
//枚举起点为1,长度为i的子串是否与起点为n-i+1,长度为i的子串匹配
}
return 0;
}