zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/dirge/p/5875035.html
Copyright © 2011-2022 走看看