HDU 5785 Interesting
求出(1,i-1)中与i构成回文的位置的和L[i],以及 i 与(i+1,n)中构成回文的位置和R[i]。
然后枚举每一对L[i]*R[i+1],累加和就是答案。
计算L[i]和R[i],可以利用manacher结果,o(n)处理得到。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } const int maxn=1000010; char str[maxn],tmp[maxn<<1]; int Len[maxn<<1],n; LL outp[maxn],out[maxn]; LL L[maxn],R[maxn]; LL mod=1000000007; struct Seg { int l,r,zx; } seg[maxn<<1]; int cnt; void init(char *st) { int len=strlen(st); tmp[0]='@'; for(int i=1;i<=2*len;i+=2) tmp[i]='#',tmp[i+1]=st[i/2]; tmp[2*len+1]='#', tmp[2*len+2]='$', tmp[2*len+3]=0; } void Manacher(char *st) { int mx=0,po=0,len=strlen(st); for(int i=1;i<=len;i++) { if(mx>i) Len[i]=min(mx-i,Len[2*po-i]); else Len[i]=1; while(st[i-Len[i]]==st[i+Len[i]]) Len[i]++; if(Len[i]+i>mx) mx=Len[i]+i, po=i; } Len[0]=1; } int main() { // File(); while(~scanf("%s",str)) { n=strlen(str); init(str); Manacher(tmp); memset(outp,0,sizeof outp); memset(out,0,sizeof out); int LEN=strlen(tmp); cnt=0; for(int i=1;i<LEN-1;i++) { if(tmp[i]=='#'&&Len[i]==1) continue; int l=i-Len[i]+1,r=i+Len[i]-1; if(tmp[l]=='#') l++,r--; l=l/2,r=r/2; seg[cnt].l=l, seg[cnt].r=r, seg[cnt].zx=(l+r+1)/2, cnt++; } LL sum=0,sz=0;int pos=0; for(int i=1;i<=n;i++) { while(pos<cnt&&seg[pos].zx<=i) { sum=sum+seg[pos].l+seg[pos].r; sz++; out[seg[pos].r]-=1; outp[seg[pos].r]-=(seg[pos].l+seg[pos].r); pos++; } L[i]=sum-sz*i; sum=sum+outp[i]; sz=sz+out[i]; } for(int i=0;i<cnt;i++) seg[i].zx=(seg[i].l+seg[i].r)/2; memset(outp,0,sizeof outp); memset(out,0,sizeof out); sum=0,sz=0,pos=cnt-1; for(int i=n;i>=1;i--) { while(pos>=0&&seg[pos].zx>=i) { sum=sum+seg[pos].l+seg[pos].r; sz++; out[seg[pos].l]-=1; outp[seg[pos].l]-=(seg[pos].l+seg[pos].r); pos--; } R[i]=sum-sz*i; sum=sum+outp[i]; sz=sz+out[i]; } LL ans=0; for(int i=1;i<=n-1;i++) ans=(ans+(L[i]%mod)*(R[i+1]%mod)%mod)%mod; printf("%lld\n",ans); } return 0; }