【题解】 seek (2019.08.12纪中【NOIP提高组】模拟 B 组T2)哈希 or KMP

题目来源:中山纪念中学

题目描述:

俗话说“好命不如好名”,小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;
}

镇图:

在这里插入图片描述

原文链接:加载失败,请重新获取