对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。
现在给出一个长度为N的01字符串,求它有多少个子串是反对称的。
对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串。比如00001111和010101就是反对称的,1001就不是。
现在给出一个长度为N的01字符串,求它有多少个子串是反对称的。
第一行一个正整数N (N <= 500,000)。第二行一个长度为N的01字符串。
一个正整数,表示反对称子串的个数。
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<bitset> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; char s[500010]; int fail[500010]; int tr[500010][26]; int len[500010]; int n,p,q; int last; int cnt[500010]; int num; ll ans; int build(int x) { len[++num]=x; return num; } int main() { scanf("%d",&n); scanf("%s",s+1); fail[0]=1,len[1]=-1,num=1; for(int i=1;i<=n;i++) { int x=s[i]-‘a‘; p=last; while((s[i-len[p]-1]==s[i]||i-len[p]-1==0)&&p!=1) { p=fail[p]; } if(s[i-len[p]-1]==s[i]||i-len[p]-1==0) { last=0; continue; } if(!tr[p][x]) { q=build(len[p]+2); int np; np=fail[p]; while((s[i-len[np]-1]==s[i]||i-len[np]-1==0)&&np!=1) { np=fail[np]; } if(s[i-len[np]-1]==s[i]||i-len[np]-1==0) { fail[q]=0; } else { fail[q]=tr[np][x]; } tr[p][x]=q; } cnt[last=tr[p][x]]++; } for(int i=num;i>=1;i--) { cnt[fail[i]]+=cnt[i]; ans+=1ll*cnt[i]; } printf("%lld",ans); }
BZOJ2084[Poi2010]Antisymmetry——回文自动机
原文:https://www.cnblogs.com/Khada-Jhin/p/10418027.html