HDU5785 manacher+差分数组

Posted Dirge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5785 manacher+差分数组相关的知识,希望对你有一定的参考价值。

用manacher算法O(n)求出所有的回文半径。有了回文半径后,就可以求出L[i]表示以i结尾的回文串的起始位置的和R[i]表示以i起始的回文串的结尾位置的和,然后就可以求出答案了,这里要注意奇偶长度回文串的不同处理。复杂度O(n)

技术分享
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e6+10;
 4 typedef long long ll;
 5 const int mod = 1e9+7;
 6 int n,m,i,r,p,f[N<<1]; char a[N],s[N<<1];
 7 ll L[N], R[N];
 8 void add(ll& a, ll b){
 9     a += b;
10     if(a >= mod||a <= -mod) a %= mod;
11 }
12 int main(){
13     while(~scanf("%s", a+1)){
14         n = strlen(a+1);
15         for(i = 1; i <= n; i++) s[i<<1] = a[i], s[i<<1|1] = #;
16         s[0] = $, s[1] = #, s[m = (n+1)<<1] = @;
17         for(r=p=0,f[1]=1,i=2;i<m;i++){
18             for(f[i]=r>i?min(r-i,f[p*2-i]):1;s[i-f[i]]==s[i+f[i]];f[i]++);
19             if(i+f[i]>r)r=i+f[i],p=i;
20         }
21 
22         memset(L, 0, sizeof(ll)*(n+5));
23         memset(R, 0, sizeof(ll)*(n+5));
24         for(i=2;i<=2*n; i++){
25             int ret = f[i]-1, pos = i/2;
26             if(ret == 0) continue ;
27             ret /= 2;
28             if(i&1){
29                 //[pos+1, pos+rer/2]
30                 add(L[pos+1], pos), add(L[pos+2], -1-pos), add(L[pos+ret+1], ret-pos), add(L[pos+ret+2], pos+1-ret);
31                 //[pos-ret/2+1, pos]
32                 add(R[pos-ret+1], pos+ret), add(R[pos-ret+2], -1-pos-ret), add(R[pos+1], -pos), add(R[pos+2], pos+1);
33             }else{
34                 //[pos, pos+ret/2]
35                 add(L[pos], pos), add(L[pos+1], -1-pos), add(L[pos+ret+1], ret-pos+1), add(L[pos+ret+2], pos-ret);
36                 //[pos-ret/2, pos]
37                 add(R[pos-ret], pos+ret), add(R[pos-ret+1], -1-pos-ret), add(R[pos+1], 1-pos), add(R[pos+2], pos);
38             }
39         }
40         for(i=1; i<=n;i++)
41             add(L[i], L[i-1]), add(R[i], R[i-1]);
42         for(i=1; i<=n;i++)
43             add(L[i], L[i-1]), add(R[i], R[i-1]);
44         ll ans = 0;
45         for(i=1;i<n;i++){
46             ans += L[i]*R[i+1];
47             if(ans >= mod||ans <= -mod)
48                 ans %= mod;
49         }
50         cout << (ans+mod)%mod << endl;
51     }
52     return 0;
53 }
View Code

 

以上是关于HDU5785 manacher+差分数组的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6230 Palindrome (manacher+树状数组)

HDU - 5785:Interesting (回文树,求相邻双回文的乘积)

HDU 5785 Function 倍增 (2016 ACM/ICPC Asia Regional Dalian Online)

HDU 3613 Best Reward(manacher求前后缀回文串)

HDU 3068 最长回文(Manacher)

HDU 3068 最长回文(manacher模板题)