Submission #1202707

#TimeUsernameProblemLanguageResultExecution timeMemory
1202707Zbyszek99Palindromes (APIO14_palindrome)C++20
73 / 100
61 ms57056 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = 1e9+50;
const ll INF_L = 1e18+40;

ll MOD[2] = {(ll)1e9+7,(ll)1e9+9};
ll prefH[300001][2];
ll p[2] = {2137,420691};
ll P[300001][2];
string s;
int n;

ll hash_(int l, int r)
{
    ll h0 = (((prefH[r][0] - prefH[l-1][0] + MOD[0]) % MOD[0]) * P[siz(s)-l][0]) % MOD[0];
    ll h1 = (((prefH[r][1] - prefH[l-1][1] + MOD[1]) % MOD[1]) * P[siz(s)-l][1]) % MOD[1];   
    return h0 * MOD[1] + h1;
}

void hash_calc()
{
    rep(d,2)
    {
        P[0][d] = 1;
        rep2(i,1,2*siz(s))
        {
            P[i][d] = (P[i-1][d] * p[d]) % MOD[d];
        }
        rep2(i,1,siz(s))
        {
            prefH[i][d] = (prefH[i-1][d] + s[i] * P[i-1][d]) % MOD[d];
        }
    }
}

struct node
{
    int l,r,link = 0, cnt = 0;
    vi sons;
};

int node_cnt = 2;
unordered_map<ll,int> node_index;
node nodes[1000001];
int suf_node[600001];

ll ans = 0;

ll dfs(int v)
{
    ll sub = nodes[v].cnt;
    forall(it,nodes[v].sons)
    {
        sub += dfs(it);
    }
    ans = max(ans,sub * (nodes[v].r-nodes[v].l+1));
    return sub;
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    cin >> s;
    s = "#" + s;
    n = siz(s)-1;
    nodes[0] = {1,0};
    nodes[1] = {0,0};
    suf_node[0] = 1;
    rep2(z,'a','z')
    {
        s = s + (char)z;
        s = s + (char)z;
    }
    hash_calc();
    int cur_poz = n+1;
    rep2(z,'a','z')
    {
        nodes[0].sons.pb(node_cnt);
        nodes[node_cnt] = {cur_poz,cur_poz,0,0};
        node_index[hash_(cur_poz,cur_poz)] = node_cnt;
        nodes[node_cnt+1] = {cur_poz,cur_poz+1,node_cnt,0};
        nodes[node_cnt].sons.pb(node_cnt+1);
        node_index[hash_(cur_poz,cur_poz+1)] = node_cnt+1;
        node_cnt+=2;
        cur_poz+=2;
    }
    rep2(i,1,n)
    {
        int cur_node = suf_node[i-1];
        while(nodes[cur_node].r >= nodes[cur_node].l)
        {
            if(s[i-(nodes[cur_node].r-nodes[cur_node].l+1)-1] == s[i])
            {
                break;
            }
            cur_node = nodes[cur_node].link;
        }
        if(nodes[cur_node].r >= nodes[cur_node].l)
        {
            int len = nodes[cur_node].r - nodes[cur_node].l+2;
            ll h = hash_(i-len,i);
            if(node_index.find(h) == node_index.end())
            {
                node_index[h] = node_cnt;
                nodes[node_cnt] = {i-len,i,0,1};
                cur_node = nodes[cur_node].link;
                while(nodes[cur_node].r >= nodes[cur_node].l)
                {
                    if(s[i-(nodes[cur_node].r-nodes[cur_node].l+1)-1] == s[i])
                    {
                        break;
                    }
                    cur_node = nodes[cur_node].link;
                }
                if(nodes[cur_node].r >= nodes[cur_node].l)
                {
                    len = nodes[cur_node].r - nodes[cur_node].l+2;
                    int cur_node = node_index[hash_(i-len,i)];
                    nodes[node_cnt].link = cur_node;
                    nodes[cur_node].sons.pb(node_cnt);
                }
                else
                {
                    int len = 0;
                    if(s[i] == s[i-1])
                    {
                        len = 1;
                    }
                    nodes[node_cnt].link = node_index[hash_(i-len,i)];
                    nodes[nodes[node_cnt].link].sons.pb(node_cnt);
                }
                node_cnt++;
            }
            else
            {
                nodes[node_index[h]].cnt++;
            }
            suf_node[i] = node_index[h];
        }
        else
        {
            int len = 0;
            if(s[i] == s[i-1])
            {
                len = 1;
            }
            nodes[node_index[hash_(i-len,i)]].cnt++;
            suf_node[i] = node_index[hash_(i-len,i)];
        }
    }
    dfs(0);
    cout << ans << "\n";
}
#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...