[POI2010]ANT-Antisymmetry

[POI2010]ANT-Antisymmetry

题意:给你一个长度为(n)(01)串,求它的非空并在异或意义下回文的子串数。

这里我们介绍马拉车的扩展:

引入(to)数组,表示每个字符与哪个字符匹配。

例如,在模板题中,有(forall c in ['a','z'],to_c=c)

而在这道题中,有(to_{'1'}='0',to_{'0'}='1')

并且我们令(to[)#(]=[)#(])

然后就可以匹配了。

注意!!这个时候初始回文串长度应为(0),因为自己不一定与自己相配。

即:

rad[i]=(i<Rpos)?min(Rpos-i,rad[Centre*2-i]):0;

最后是(0)不是(1)

另,统计答案时应是:

Ans+=(rad[i]>>1);

因为加入了辅助字符 # ,所以数量要减半。

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int S,rad[1001000],Rpos,Centre,Ans;
char s[1001000],to[129];
void getln(){
	char c=getchar();
	to['0']='1',to['1']='0',to['$']='$';
	s[0]='$',S=1;
	while(c!='0'&&c!='1')c=getchar();
	while(c=='0'||c=='1')s[S++]=c,s[S++]='$',c=getchar();
	s[S]='';
}
void Manacher(){
	Rpos=Centre=-1;
	for(int i=0;i<S;i++){
		rad[i]=(i<Rpos)?min(Rpos-i,rad[Centre*2-i]):0;
		while(i-rad[i]>=0&&i+rad[i]<S)if(to[s[i-rad[i]]]==s[i+rad[i]])rad[i]++;else break;
		if(i+rad[i]>Rpos)Rpos=i+rad[i],Centre=i;
		Ans+=(rad[i]>>1);
	}
}
signed main(){
	scanf("%lld",&S);
	getln();
	Manacher();
	printf("%lld",Ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Troverld/p/12772339.html