HDU5785 Interesting(回文串&&前缀和)

来源:互联网 发布:西直门桥数据 编辑:程序博客网 时间:2024/05/18 10:54

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5787

题意:

找出所有相邻的回文串,将它们最外侧的端点坐标乘积都加起来,(i,j),(j+1,k) 两个回文串,将所有的i*k加和。

思路:

回文串直接用Manacher求解,然后对于所有的回文串都包含许多小的回文串,例如(i,j)回文串同时代表(i+1,j-1)等许多回文串,所以需要将更新的值看为一个区间,然后将所有区间求和,分别处理每个点作为回文串左右端点的情况,最后乘积求和即可。

代码:

//kopyh#include <bits/stdc++.h>#define MOD 1000000007#define N 2000005using namespace std;int n,m,sum,res,flag,tot;int p[N*2];int Manacher(char *str){    int res=0,ans=0,len=strlen(str);    for(int i=len;i>=0;i--)    {        str[i+i+2] = str[i];        str[i+i+1] = '#';    }    str[0] = '*';    for(int i=2;i<2*len+1;i++)    {        if(p[res]+res > i)            p[i] = min(p[2*res-i],p[res]+res-i);        else            p[i] = 1;        while(str[i-p[i]] == str[i+p[i]])            p[i]++;        if(res+p[res]<i+p[i])res=i;        if(ans<p[i])ans=p[i];    }    return ans-1;}char s[N];long long a1[N],a2[N],b1[N],b2[N],aa[N],bb[N],ta[N],tb[N];int main(){    int i,j,k,cas,T,t,x,y,z;    while(scanf("%s",s)!=EOF)    {        n=strlen(s);        Manacher(s);        m=strlen(s);        sum=0;tot=0;        memset(a1,0,sizeof(a1));        memset(b1,0,sizeof(b1));        memset(a2,0,sizeof(a2));        memset(b2,0,sizeof(b2));        memset(ta,0,sizeof(ta));        memset(tb,0,sizeof(tb));        for(i=2;i<m-1;i++)        {            t=p[i]-1;            y=i+t;if(y&1)y--;            x=i-t;if(x&1)x++;            x/=2;y/=2;            int mm=(x+y+1)/2;            a1[mm]+=(y-x)&1?mm-1:mm; a1[mm]%=MOD; ta[mm]++;            a2[y]+=x; a2[y]%=MOD; ta[y]--;            mm = (x+y)/2;            b1[x]+=y; b1[x]%=MOD; tb[x]++;            b2[mm]+=(y-x)&1?mm+1:mm; b2[mm]%=MOD; tb[mm]--;        }        long long x=0,y=0,z=0;        for(i=1,j=0;i<=n;i++)        {            x-=y; x+=MOD; x%=MOD;            x+=a1[i]; aa[i]=x;            x-=a2[i]; y+=ta[i];        }        x=0,y=0,z=0;        for(i=1,j=0;i<=n;i++)        {            x-=y; x+=MOD; x%=MOD;            x+=b1[i]; bb[i]=x;            x-=b2[i]; y+=tb[i];        }        long long res=0;        for(i=2;i<=n;i++)            res = (res+aa[i-1]*bb[i])%MOD;        printf("%I64d\n",res%MOD);    }    return 0;}








0 0