BZOJ 2084 二分+hash OR Manacher
思路:
二分+哈希
//By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=500050; const ll mod=1000000007; int n; ll hs1[N],hs2[N],base[N],Ans; char s1[N],s2[N]; int main(){ scanf("%d",&n); scanf("%s",s1+1),base[0]=1; for(int i=1;i<=n;i++) hs1[i]=(hs1[i-1]*50+s1[i])%mod, s2[i]=s1[i]=='1'?'0':'1',base[i]=base[i-1]*50%mod; for(int i=n;i;i--)hs2[i]=(hs2[i+1]*50+s2[i])%mod; for(int i=1;i<n;i++){ int l=0,r=min(n-i,i),ans=0; while(l<=r){ int mid=(l+r)>>1; if(((hs1[i]-hs1[i-mid]*base[mid]%mod)+mod)%mod==((hs2[i+1]-hs2[i+mid+1]*base[mid]%mod)+mod)%mod) l=mid+1,ans=mid; else r=mid-1; } Ans+=ans; }printf("%lld\n",Ans); }
Manacher改一下条件
0只能匹配1 1只能匹配0 #匹配#
(长度从0开始匹配 这样就相当于只能从#开始走了 也就是长度为偶数)
//By SiriusRen #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; const int N=1000050; ll ans; int n,p[N]; char s[N],ch[N]; bool cmp(char x,char y){return (x=='#'&&y=='#')||(x=='1'&&y=='0')||(x=='0'&&y=='1');} void Manacher(){ int mx=0,id=0; for(int i=1;i<=n;i++){ if(mx>i)p[i]=min(p[id*2-i],p[id]+id-i); else p[i]=0; while(cmp(s[i-p[i]],s[i+p[i]]))p[i]++; if(i+p[i]>mx)mx=i+p[i],id=i; ans+=p[i]/2; } } int main(){ scanf("%d",&n); scanf("%s",ch+1); s[1]='#'; for(int i=1;i<=n;i++)s[i<<1]=ch[i],s[i<<1|1]='#'; n=n<<1|1;Manacher(); printf("%lld\n",ans); }