BZOJ 2084 Poi2010 Antisymmetry Manacher
题意:
对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。
现在给出一个长度为N的01字符串,求它有多少个子串是反对称的。
Input
第一行一个正整数N (N <= 500,000)。第二行一个长度为N的01字符串。
Output
一个正整数,表示反对称子串的个数。
Sample Input
8
11001011
11001011
Sample Output
7
规定“#’=‘#’ 1!=1 ,0!=0,1=0
然后就Manacher 就好了
#define MAXN 500005 #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #define min(a,b) (a)<(b)?(a):(b) int len,s[MAXN<<1],p[MAXN<<1]; char ch[MAXN]; long long Ans; void Manacher(){ int id=0; for(int i=1;i<=2*len+1;i+=2){ if(p[id]+id>i)p[i]=min(p[2*id-i],p[id]+id-i); else p[i]=1; while((s[i-p[i]]==s[i+p[i]]&&s[i+p[i]]==3)||(s[i-p[i]]==0&&s[i+p[i]]==1)||(s[i-p[i]]==1&&s[i+p[i]]==0)) p[i]++; if(p[i]+i>p[id]+id)id=i; Ans+=(p[i]-1)>>1; } } int main(){ scanf("%d%s",&len,ch+1); for(int i=0;i<=len;i++)s[i*2]=ch[i]-'0',s[i*2+1]=3; s[0]=4; Manacher(); printf("%lld",Ans); }