hdoj5785

题意:略

先用题解的办法,manacher,然后tag,add数组。但是比较难办的是manacher加了新的字符。这样的话cntL和cntR不是实际的值,但是没关系,原本的字符都在奇数位置,这样cntL[i]就等于(add[i]-tag[i])/2就是真实值,具体来说不好看,我看了3个小时才明白。比如

$#a#a#a#

12345678(下标)

01234321(radius)

那么第一个a,i=3时cntL+3,i=4时cntL+5,i=5时cntL+7。实际上是+1,+2,+3的。而tag表示它被加过几次。因此1+2+3=(3+5+7-3)/2;除法用逆元。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <stack>
#include <bitset>
#define mkp make_pair
using namespace std;
const double EPS=1e-8;
typedef long long lon;
const lon SZ=1000010,SSZ=2*SZ,INF=0x7FFFFFFF,mod=1000000007;
char src[SSZ],ch[SSZ];
lon slen,clen,rd[SSZ];
lon cntr[SSZ],cntl[SSZ];
lon add[SSZ],tag[SSZ],inv;

void init()
{
    slen=strlen(src+1);
    clen=0;
    ch[++clen]='$';
    ch[++clen]='#';
    for(lon i=1;i<=slen;++i)
    {
        ch[++clen]=src[i];
        ch[++clen]='#';
    }
}

lon ext(lon ct,lon pos,lon &maxr,lon &maxid)
{
    lon res=0;
    for(lon i=pos;i<=clen;++i)
    {
        lon ll=ct-(i-ct);
        if(ch[ll]==ch[i])++res;
        else break;
    }
    return res;
}

void manacher()
{
    lon maxr=0,maxid=0;
    for(lon i=2;i<=clen;++i)
    {
        if(i<=maxr)
        {
            lon rf1=maxid-(i-maxid);
            lon rf2=maxid-(maxr-maxid);
            lon ll=(rf1-rd[rf1]+1);
            if(ll>rf2)rd[i]=rd[rf1];
            else rd[i]=(maxr-i+1)+ext(i,maxr+1,maxr,maxid);
        }
        else
        {
            rd[i]=ext(i,i,maxr,maxid);
        }
        if(i+rd[i]-1>maxr)
        {
            maxr=i+rd[i]-1;
            maxid=i;
        }
    }
}

void work()
{
    manacher();
    for(lon i=2;i<=clen;++i)
    {
        lon ll=i-rd[i]+1,rr=i+rd[i]-1;
        ++tag[ll],add[ll]+=(i+rd[i]-1)+1;
        --tag[i+1],add[i+1]-=i;
    }
    for(lon i=2;i<=clen;++i)
    {
        //cout<<tag[i]<<" "<<add[i]<<endl;
        tag[i]+=tag[i-1];
        add[i]+=add[i-1]-tag[i];
        add[i]%=mod;
        cntr[i]=(add[i]-tag[i])*inv%mod;
        //cout<<cntr[i]<<endl;
    }
    for(lon i=0;i<=clen+1;++i)
    {
        tag[i]=add[i]=0;
    }
    for(lon i=2;i<=clen;++i)
    {
        lon rr=i+rd[i]-1,ll=i-rd[i]+1;
        ++tag[rr],add[rr]+=(i-rd[i]+1)-1;
        --tag[i-1],add[i-1]-=i;
    }
    for(lon i=clen;i>=2;--i)
    {
        tag[i]+=tag[i+1];
        add[i]+=add[i+1]+tag[i];
        add[i]%=mod;
        cntl[i]=(add[i]-tag[i])*inv%mod;
    }
    for(lon i=0;i<=clen+1;++i)
    {
        tag[i]=add[i]=0;
    }
    lon res=0;
    for(lon i=3;i<clen;i+=2)
    {
        //cout<<cntl[i]<<" "<<cntr[i+1]<<endl;
        res+=cntl[i]*cntr[i+2];
        res%=mod;
    }
    res=(res+mod)%mod;
    cout<<res<<endl;
    for(lon i=0;i<=clen+1;++i)
    {
        cntl[i]=cntr[i]=rd[i]=0;
    }
}

void ex_gcd(lon a,lon b,lon &x,lon &y,lon &d)
{
    if(b==0)
    {
        d=a,x=1,y=0;
    }
    else
    {
        ex_gcd(b,a%b,y,x,d);
        y-=(a/b)*x;
    }
}

int main()
{
    //std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    lon x,y,d;
    ex_gcd(2,mod,x,y,d);
    inv=x;
    lon casenum;
    //cin>>casenum;
    //cout<<casenum<<endl;
    //for(lon time=1;time<=casenum;++time)
    for(int time=1;scanf(" %s",src+1)!=EOF;++time)
    {
        init();
        work();
    }
    return 0;
}

 

posted @ 2019-04-09 17:29  degvx  阅读(156)  评论(0)    收藏  举报