CF17E Palisection(manacher)
题意
给出一个长度为N的字符串S,问S中有多少个回文子串对(i,j)使得i,j在S中的位置相交?
(N<=2*106)
题解
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const long long N=2001000; 8 const long long mod=51123987; 9 char s[N*2],str[N*2]; 10 long long p[N*2],n,m,f[N*2],g[N*2],sum,ans,tot,num; 11 void init(){ 12 str[0]=str[1]='#'; 13 for(long long i=1;i<=n;i++){ 14 str[i*2]=s[i]; 15 str[i*2+1]='#'; 16 } 17 m=n*2+1; 18 } 19 void manacher(){ 20 long long mx=0,id; 21 for(long long i=1;i<=m;i++){ 22 if(mx>i)p[i]=min(p[id-(i-id)],p[id]+id-i); 23 else p[i]=1; 24 while(str[i-p[i]]==str[i+p[i]])p[i]++; 25 if(i+p[i]-1>mx)mx=i+p[i]-1,id=i; 26 } 27 } 28 int main(){ 29 scanf("%lld",&n); 30 scanf("%s",s+1); 31 init(); 32 manacher(); 33 for(long long i=1;i<=m;i++){ 34 f[i]++; 35 f[i+p[i]-1+1]--; 36 g[i]++; 37 g[i-p[i]+1-1]--; 38 } 39 for(long long i=1;i<=m;i++){ 40 f[i]+=f[i-1]; 41 f[i]%=mod; 42 } 43 for(long long i=m;i>=1;i--){ 44 g[i]+=g[i+1]; 45 g[i]%=mod; 46 } 47 for(long long i=1;i<=n;i++){ 48 ans+=g[i*2]*sum; 49 ans%=mod; 50 sum+=f[i*2]; 51 sum%=mod; 52 num+=f[i*2]; 53 num%=mod; 54 } 55 printf("%lld",((num-1)*num/2%mod-ans+mod)%mod); 56 return 0; 57 }