如何利用字符串哈希求一个字符串是否是回文串?只需要设计一种求哈希值的方式,使得不是回文串的字符串正哈希(正着遍历得到的)和负哈希(反着遍历得到的)的值不同且使得回文串的正哈希和负哈希的值相同,这样就能通过正负哈希值是否相同来判断字符串是否是回文串了,那么这个求哈希值的方法是什么呢?可以是遍历字符串,每个元素的值乘当前数组的下标然后加和,这个很容易证明,我也是诈胡想出来的= =。然后这个值怎么维护呢?可以利用一些前缀和的思想,我们开四个数组,dat数组存放字符串,zheng数组维护从字符串开始到当前元素的正哈希值,fan数组维护从字符串开始到当前元素的负哈希值,he数组维护从字符串开始到当前元素的总和,很明显当我们正着遍历字符串的时候,zheng[i]=zheng[i-1]+int(dat[i])*pos(pos是当前元素数组下标),he[i]=he[i-1]+int(dat[i]),fan[i]=fan[i-1]+he[i-1](这个模拟一下就能发现),这样当zheng[pos]==fan[pos]时就说明从字符串开头到当前元素这一段是回文串,可是题目中让我们判断的是M串,M串从中间劈开两边都是回文串,所以它本身也是回文串,这样判断一个字符串是是M串只需判断它本身是回文串并且它的1/2也是回文串即可,在程序中加上对应的判断语句即可,还有一点要注意,单个字符也是M串,前面如果没有特判,那么后面结果不要忘记加1。
下面是代码:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
char dat[200005];
ll zheng[200005];
ll fan[200005];
ll he[200005];
int main()
{
int ans=0;
int length;
cin>>dat;
length=strlen(dat);
he[0]=int(dat[0]);
for(int i=1;i<length;++i)
{
zheng[i]=zheng[i-1]+int(dat[i])*i;
he[i]=he[i-1]+int(dat[i]);
fan[i]=fan[i-1]+he[i-1];
if(zheng[i]==fan[i])
{
if(i%2==0)
{
if(zheng[i/2]==fan[i/2])
{
ans++;
}
}
else
{
if(zheng[(i-1)/2]==fan[(i-1)/2])
{
ans++;
}
}
}
}
cout<<ans+1<<endl;
return 0;
}