对于一个0/1字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作「反对称」字符串。比如00001111和010101就是反对称的,而1001就不是。
现在给出一个长度为n的0/1字符串,求它有多少个子串是反对称的,注意这里相同的子串出现在不同的位置会被重复计算。
标签:bsp can BMI href 正整数 char += const typedef
8
11001011
7
对于100%的数据,1≤n≤500000。
马拉车裸题。
马拉车算法:https://www.cnblogs.com/grandyang/p/4475985.html
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e6+10; int p[maxn],n,len; ll ans; char s[maxn],ms[maxn]; bool check(char x,char y){ if(((x-‘0‘)^(y-‘0‘))==1) return 1; if(x==‘#‘ && y==‘#‘) return 1; return 0; } void init(char *s){ ms[0]=‘$‘,ms[1]=‘#‘; for (int i=0; s[i]; i++){ ms[i*2+2]=s[i]; ms[i*2+3]=‘#‘; } len=strlen(s)*2+2; ms[len]=‘$‘; } inline ll calc(){ ans=0; for (int i=1; i<len; i+=2) ans+=1ll*(p[i]>>1); return ans; } void manacher(char *s){ init(s); int mx=0,id=0; for (int i=1; i<len; i+=2){ p[i]=(mx>i)?min(p[2*id-i],mx-i):1; while(check(ms[i+p[i]],ms[i-p[i]])) p[i]++; if(mx<i+p[i]){ mx=i+p[i]; id=i; } } printf("%lld\n",calc()); } int main(){ scanf("%d%s",&n,s); manacher(s); return 0; }
标签:bsp can BMI href 正整数 char += const typedef
原文地址:https://www.cnblogs.com/acerkoo/p/9769252.html