Codeforces 17E Palisection

開始想的時候神遊去了,發呆了好久。。。。2333,其實這題就是一個manacher+遞推

想法還是很簡單,但是。。。判邊界真是噁心到我了。。。值得玩一玩

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;

#define N 2000010
#define Mod 51123987

int n,m,p[N*2],flag1[N],flag2[N];
char S[N*2];
long long Start[N],End[N],sum[N],total,Ans;

void Manacher()
{
    int x=1,m=0;
    for(int i=1;i<=n;i++)
    {
        p[i]=1;
        if(m>i)
            p[i]=min(m-i,p[2*x-i]);
        while(S[i-p[i]]==S[i+p[i]])
            p[i]++;
        total=(total+p[i]/2)%Mod;
        int pos=i/2,len=p[i]-1;
        flag1[pos-(len+1)/2+1]++;flag1[pos+1]--;
        if(len%2==0)
        {
            flag2[pos]--;flag2[pos+(len+1)/2]++;
        }
        else
        {
            flag2[pos-1]--;flag2[pos+(len+1)/2-1]++;
        }
        if(i+p[i]-1>m)
            m=i+p[i]-1,x=i;
    }
}

int main()
{
    scanf("%d",&n);
    scanf("%s",S);
    for(int i=n;i>=0;i--)
        S[i*2+1]='#',S[i*2+2]=S[i];
    S[0]='$';
    n=n*2+1;
    Manacher();
    n>>=1;
    long long Add=0;
    for(int i=1;i<=n;i++)
    {
        Add=(Add+flag1[i])%Mod;
        Start[i]=(Start[i]+Add)%Mod;
    }
    Add=0;
    for(int i=n;i>=1;i--)
    {
        Add=(Add+flag2[i])%Mod;
        End[i]=(End[i]+Add)%Mod;
    }
    for(int i=1;i<=n;i++)
        sum[i]=(sum[i-1]+End[i])%Mod;
    for(int i=1;i<=n;i++)
    {
        Ans=(Ans+(Start[i]*sum[i-1]%Mod))%Mod;
    }
    total=(total*(total-1)/2)%Mod;
    Ans=((total-Ans)%Mod+Mod)%Mod;
    cout<<Ans<<endl;
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章