【[POI2010]ANT-Antisymmetry】

开始复习字符串了

第一步肯定得是\(hash\)

首先理性分析一波不可能出现长度为奇数的反回文串,对称轴位置取反之后肯定和原来不相等了

我们可以枚举所有回文串的对称中心,之后我们发现这个样子是具有单调性de

于是我们就利用\(hash\)来判断

将原来的串取反之后在反转,判断在对称中心左右两边二分的长度是否相等就可以啦

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define re register
#define ull unsigned long long
#define maxn 500005
#define min(a,b) ((a)<(b)?(a):(b))
char S[maxn],T[maxn];
int a[maxn],b[maxn];
int n;
ull ha[maxn],sh[maxn];
ull pow[maxn];
ull base=17;
long long num;
inline ull get_hash(int l,int r,int op)
{
	if(!op) return ha[r]-ha[l-1]*pow[r-l+1];
	return sh[n-l+1]-sh[n-r]*pow[r-l+1];
}
int main()
{
	scanf("%d",&n);
	scanf("%s",S+1);
	for(re int i=1;i<=n;i++)
		if(S[i]=='0') a[i]=0;
			else a[i]=1;
	pow[0]=1;
	for(re int i=1;i<=n;i++)
		pow[i]=pow[i-1]*base;
	for(re int i=1;i<=n;i++)
		ha[i]=ha[i-1]*base+(a[i]+1);
	for(re int i=1;i<=n;i++)
		b[i]=a[n-i+1]^1;
	for(re int i=1;i<=n;i++)
		sh[i]=sh[i-1]*base+(b[i]+1);
	for(re int i=1;i<n;i++)
	{
		int l=1,r=min(i,n-i);
		int ans=0;
		while(l<=r)
		{
			int mid=l+r>>1;
			if(get_hash(i-mid+1,i,1)==get_hash(i+1,i+mid,0)) l=mid+1,ans=mid;
			else r=mid-1;
		}
		num+=ans;
	}
	printf("%lld\n",num);
	return 0;
}
/*
8
11001011
*/
posted @ 2019-01-01 21:41  asuldb  阅读(165)  评论(0编辑  收藏  举报