【Ybtoj 第7章 例题2】回文子串【哈希】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路

我们可以用二分+哈希来做,首先从前后两端分别哈希一次,然后枚举回文串的中心(对称点),二分对称字符串长度,根据哈希直接判断中心点两端字符串是否相同,然后就没了。。

PS:长度要分成奇偶两种分别做,奇数时字符串长度为2mid+1,偶数时为2mid。


代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <cmath>
using namespace std;

typedef unsigned long long ull;

ull p=131;
ull a[1000010],base[1000010],b[1000010];
int n,ans,cnt;
string s;

bool check()
{
    
    
	if(s[0]=='E'&&s[1]=='N'&&s[2]=='D')
		return 1;
	return 0;
}

void hash()
{
    
    
	memset(base,0,sizeof(base));
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	base[0]=1ull;
	for(int i=0; i<n; i++) {
    
    
		base[i+1]=base[i]*p;
		a[i+1]=a[i]*p+(s[i]-'a');//正序字符串哈希
	}
	for(int i=n-1; i>=0; i--)
		b[i+1]=b[i+2]*p+(s[i]-'a');//倒序字符串哈希
}

void work()
{
    
    
	for(int i=1; i<=n; i++) {
    
    //找中心
		int mid=0,l=0,r=n;
		while(l<=r) {
    
    //长度奇数
			mid=(l+r)>>1;
			if(i-mid<1||i+mid>n)
			{
    
    
				r=mid-1;
				continue;
			}
			if(a[i]-a[i-mid-1]*base[mid+1]==b[i]-b[i+mid+1]*base[mid+1])
			{
    
    
				ans=max(ans,mid*2+1);
				l=mid+1;
			}
			else r=mid-1;
		}
		mid=0,l=0,r=n;
		while(l<=r) {
    
    //长度偶数
			mid=(l+r)>>1;
			if(i-mid+1<1||i+mid>n)
			{
    
    
				r=mid-1;
				continue;
			}
			if(a[i]-a[i-mid]*base[mid]==b[i+1]-b[i+mid+1]*base[mid])
			{
    
    
				ans=max(ans,mid*2);
				l=mid+1;
			}	
			else r=mid-1;
		}
	}

}
int main()
{
    
    
	cin>>s;
	n=s.size();
	while(!check()) {
    
    
		cnt++;
		ans=1;
		hash();
		work();
		printf("Case %d: %d\n",cnt,ans);
		cin>>s;
		n=s.size();
	}
}



猜你喜欢

转载自blog.csdn.net/kejin2019/article/details/113144051