题目链接:hdu 5785 Interesting
题意:
有一个长度为n的串(n<=10^6),对 1 <= i <= j < k <= length(s) . 如果[i,j]和[j+1,k]都是回文串。则对答案的贡献为 i*k ,求贡献和。
题解:
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef long long ll; 5 6 const int N=1e6+7,P=1e9+7; 7 8 struct Manacher{ 9 char str[N*2]; 10 int p[N*2],len,mx,id,tl,ans,i; 11 void maxlen(char *s){ 12 len=strlen(s),mx=0,id=0,tl=0,str[tl++]=‘$‘,str[tl++]=‘#‘; 13 for(i=0;i<len;i++)str[tl++]=s[i],str[tl++]=‘#‘; 14 for(i=2,str[tl]=0,ans=0;i<tl;i++){ 15 p[i]=mx>i?min(p[(id<<1)-i],mx-i):1; 16 while(str[i-p[i]]==str[i+p[i]])p[i]++; 17 if(i+p[i]>mx)mx=i+p[i],id=i; 18 } 19 } 20 }M; 21 char s[N]; 22 int dp[N*2][4],ans; 23 24 void add(int op,int l,int r,int v) 25 { 26 if(l>r)return; 27 dp[l][op]=(dp[l][op]+v)%P; 28 dp[r+1][op]=(dp[r+1][op]-v)%P; 29 } 30 31 int main(){ 32 while(~scanf("%s",s)) 33 { 34 memset(dp,0,sizeof(dp)); 35 M.maxlen(s); 36 F(i,1,M.tl-2) 37 { 38 add(0,i,M.p[i]+i-1,i); 39 add(1,i,M.p[i]+i-1,1); 40 add(2,i-M.p[i]+1,i,i); 41 add(3,i-M.p[i]+1,i,1); 42 } 43 F(j,1,M.tl)F(i,0,3)dp[j][i]=(dp[j][i]+dp[j-1][i]+P)%P; 44 ans=0; 45 for(int i=4;i<M.tl;i+=2) 46 { 47 ll a=(dp[i][2]-1ll*dp[i][3]*(i/2)%P+P)%P; 48 ll b=(dp[i-2][0]-1ll*dp[i-2][1]*((i-2)/2)%P+P)%P; 49 ans=(a*b%P+ans)%P; 50 } 51 printf("%d\n",ans); 52 } 53 return 0; 54 }
hdu 5785 Interesting(manacher+前缀和)
原文:http://www.cnblogs.com/bin-gege/p/7215528.html