제출 #713062

#제출 시각아이디문제언어결과실행 시간메모리
713062bin9638Palindromes (APIO14_palindrome)C++17
100 / 100
908 ms67736 KiB
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define pb push_back
#define N 300010
#define ii pair<int,int>
#define fs first
#define sc second
#define ld double

int n;
string s;
ll ans=0;

/*struct BIT
{
    int bit[N]={};

    void init()
    {
        memset(bit,0,sizeof(bit));
    }

    void update(int u,int val)
    {
        for(;u<=n;u+=u&(-u))
            bit[u]+=val;
    }

    int get(int u)
    {
        int res=0;
        for(;u>0;u-=u&(-u))
            res+=bit[u];
        return res;
    }
}BIT;*/

struct DoubleHash
{
    vector<ll> H1, H2, p1, p2;
    ll base1 = 311, base2 = 313, mod1 = 1e9 + 8277, mod2 = 1e9 + 9277;
    void init(string s, int n)
    {
        p1.resize(n + 1, 1), p2.resize(n + 1, 1), H1.resize(n + 1, 0), H2.resize(n + 1, 0);
        for (int i = 1; i <= n; i++)
        {
            p1[i] = p1[i - 1] * base1 % mod1;
            p2[i] = p2[i - 1] * base2 % mod2;
            H1[i] = (H1[i - 1] * base1 + s[i]-'A'+1) % mod1;
            H2[i] = (H2[i - 1] * base2 + s[i]-'A'+1) % mod2;
        }
    }
    ll getHash(int u, int v)
    {
        ll t1 = (H1[v] - H1[u - 1] * p1[v - u + 1] + mod1 * mod1) % mod1;
        ll t2 = (H2[v] - H2[u - 1] * p2[v - u + 1] + mod2 * mod2) % mod2;
        return t1 * 1000000000 + t2;
    }
}xuoi,nguoc;

bool check_palin(int l,int r)
{
    return (xuoi.getHash(l,r)==nguoc.getHash(n-r+1,n-l+1));
}
struct SA
{
    int sa[N]={},pos[N]={},lcp[N]={},cnt[N]={},tmp[N]={};
bool SS(int u,int v,int k)
{
    if(pos[u]!=pos[v])
        return pos[u]<pos[v];
    if(u+k<=n&&v+k<=n)
        return pos[u+k]<pos[v+k];
    return(u>v);
}

void countsort(int k)
{
    fill(cnt,cnt+1+max(256,n),0);
    for(int i=1;i<=n;i++)
        cnt[(i+k<=n ? pos[i+k] : 0)]++;
    for(int i=1;i<=max(256,n);i++)
        cnt[i]+=cnt[i-1];
    for(int i=n;i>=1;i--)
        tmp[cnt[(sa[i]+k<=n ? pos[sa[i]+k] : 0)]--]=sa[i];
    for(int i=1;i<=n;i++)
        sa[i]=tmp[i];
}

void make_SA()
{
    for(int i=1;i<=n;i++)
    {
        sa[i]=i;
        pos[i]=s[i];
    }
    for(int k=1;k<=n;k<<=1)
    {
        countsort(k);
        countsort(0);
        tmp[sa[1]]=1;
        for(int i=2;i<=n;i++)
            tmp[sa[i]]=tmp[sa[i-1]]+SS(sa[i-1],sa[i],k);
        for(int i=1;i<=n;i++)
            pos[i]=tmp[i];
    }
}

void make_lcp()
{
    for(int i=1;i<=n;i++)
        pos[sa[i]]=i;
    int k=0;
    for(int i=1;i<=n;i++)
    {
        if(pos[i]==n)
        {
            lcp[pos[i]]=0;
            continue;
        }
        int j=sa[pos[i]+1];
        while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])
            k++;
        lcp[pos[i]]=k;
        k-=(k>0);
    }
}

vector<int>gop[N];

void build()
{
    for(int i=1;i<n;i++)
        gop[lcp[i]].pb(i);
}
}SA;

struct DSU
{
    int dem=0,lab[N]={},sz[N]={};

    void init()
    {
        dem=0;
        memset(lab,-1,sizeof(lab));
        memset(sz,0,sizeof(sz));
    }

    int root(int u)
    {
        if(lab[u]<0)
            return u;
        return(lab[u]=root(lab[u]));
    }

    void update(int u,int v)
    {
        if((u=root(u))==(v=root(v)))
            return;
        if(lab[u]>lab[v])
            swap(u,v);
        lab[u]+=lab[v];
        lab[v]=u;
        sz[u]+=sz[v];
        dem=max(dem,sz[u]);
    }

    void them(int u)
    {
        u=root(u);
        dem=max(dem,++sz[u]);
    }
}DSU;

struct le
{
    vector<int>lis[N];

    void solve()
    {
        //BIT.init();
        DSU.init();
        for(int i=1;i<=n;i++)
        {
            int val=0,l=1,r=min(i,n-i+1);
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(check_palin(i-mid+1,i+mid-1))
                {
                    val=mid;
                    l=mid+1;
                }else
                    r=mid-1;
            }
            lis[val].pb(SA.pos[i]);
        }
        for(int length=n;length>=1;length--)
        {
             for(auto u:lis[length])
                DSU.them(u);
             for(auto u:SA.gop[length])
                DSU.update(u,u+1);
             ans=max(ans,1ll*DSU.dem*(length*2-1));
        }
    }
}le;

struct chan
{
    vector<int>lis[N];

    void solve()
    {
        //BIT.init();
        DSU.init();
        for(int i=1;i<=n;i++)
        {
            int val=0,l=1,r=min(i-1,n-i+1);
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(check_palin(i-mid,i+mid-1))
                {
                    val=mid;
                    l=mid+1;
                }else
                    r=mid-1;
            }
            lis[val].pb(SA.pos[i]);
        }
        for(int length=n;length>=1;length--)
        {
             for(auto u:lis[length])
                DSU.them(u);
             for(auto u:SA.gop[length])
                DSU.update(u,u+1);
             ans=max(ans,1ll*DSU.dem*(length*2));
        }
    }
}chan;

int main()
{
    #ifdef SKY
    freopen("A.inp","r",stdin);
    freopen("A.out","w",stdout);
    #endif // SKY
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>s;
    n=s.size();
    s=" "+s;
    for(int i=1;i*2<=n;i++)
        swap(s[i],s[n-i+1]);
    nguoc.init(s,n);
    for(int i=1;i*2<=n;i++)
        swap(s[i],s[n-i+1]);
    xuoi.init(s,n);
    SA.make_SA();
    SA.make_lcp();
    SA.build();
    //cout<<s<<endl;
   // for(int i=1;i<=n;i++)cout<<SA.sa[i]<<" "<<SA.lcp[i]<<endl;
    le.solve();
    chan.solve();
    cout<<ans;
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...