模拟赛20200327 T3 回文串 (二分+双哈希求回文)

在这里插入图片描述
在这里插入图片描述
题很水,但是我第一发前缀和没有处理到n+1,第二发哈希底数137 mod 1e9+7被卡,第三发双哈希一个取模一个自然溢出都用ULL,取模的那个中间过程出现负数自动模了264。。。时运不齐,命途多舛。
双哈希先用自然溢出的判断会快很多,减少取模。

Code:

#include<bits/stdc++.h>
#define maxn 800005
using namespace std;
const int Seed = 137, mod = 1e9+7;
typedef unsigned long long ULL;
typedef long long LL;
struct str{
	char s[maxn];
	int n;
	ULL F[maxn][2],p[maxn][2],G[maxn][2],f[maxn]; LL sum[maxn];
	inline int V(int l,int r,bool t){
		if(t) return F[r][1]-F[l-1][1]*p[r-l+1][1];
		return (F[r][0]+mod-F[l-1][0]*p[r-l+1][0]%mod)%mod;
	}
	inline bool check(int l,int r){
		if(F[r][1]-G[l][1]!=(F[l-1][1]-G[r+1][1])*p[r-l+1][1]) return 0;
		return (F[r][0]+mod-G[l][0]+(G[r+1][0]+mod-F[l-1][0])*p[r-l+1][0])%mod==0;
	}
	void build(bool flg){
		n=strlen(s+1),p[0][0]=p[0][1]=1;
		if(flg) reverse(s+1,s+1+n);
		for(int i=1;i<=n;i++){
			F[i][0]=(F[i-1][0]*Seed+s[i])%mod,p[i][0]=p[i-1][0]*Seed%mod;
			F[i][1]=(F[i-1][1]*Seed+s[i]),p[i][1]=p[i-1][1]*Seed;
		}
		for(int i=n;i>=1;i--)
			G[i][0]=(G[i+1][0]*Seed+s[i])%mod,G[i][1]=G[i+1][1]*Seed+s[i];
		for(int i=1;i<=n;i++){
			int l=0,r=min(i-1,n-i),mid;
			while(l<r) mid=(l+r+1)>>1,check(i-mid,i+mid)?(l=mid):(r=mid-1);
			f[i-l]++,f[i+1]--;
			if(i<n){
				l=0,r=min(i,n-i);
				while(l<r) mid=(l+r+1)>>1,check(i-mid+1,i+mid)?(l=mid):(r=mid-1);
				f[i-l+1]++,f[i+1]--;
			}
		}
		for(int i=1;i<=n+1;i++) f[i]+=f[i-1],sum[i]=sum[i-1]+f[i];
	}
}A,B;
int Q,x,y;
int main()
{
	freopen("palindrome.in","r",stdin);
	freopen("palindrome.out","w",stdout);
	scanf("%*s%s%s%d",A.s+1,B.s+1,&Q);
	A.build(0),B.build(1);
	while(Q--){
		scanf("%d%d",&x,&y);
		int l=0,r=min(A.n-x,B.n-y)+1,mid;
		while(l<r) mid=(l+r+1)>>1,
			A.V(x,x+mid-1,1)==B.V(y,y+mid-1,1)&&A.V(x,x+mid-1,0)==B.V(y,y+mid-1,0)?(l=mid):(r=mid-1);
		printf("%lld\n",A.sum[x+l]-A.sum[x]+B.sum[y+l]-B.sum[y]+l);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值