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

Sample Output

7


显然是Manacher模板题
规定“#’=‘#’  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);
}






posted @ 2017-07-09 12:10  cooook  阅读(62)  评论(0编辑  收藏  举报