Submission #1284571

#TimeUsernameProblemLanguageResultExecution timeMemory
1284571ducanh0811Lampice (COCI19_lampice)C++20
0 / 110
5095 ms10448 KiB
#include <bits/stdc++.h>
#define int long long
#define FOR(i, a, b) for (int i = (a), _b = (b); i <= _b; ++i)
#define REV(i, a, b) for (int i = (a), _b = (b); i >= _b; --i)
using namespace std;

bool M1;
#define MAXN 50505
int numNode; 
string nodeChar; 
int intChar[MAXN]; 
vector<int> g[MAXN];
bool block[MAXN]; 
int sizeTree[MAXN];
int parent[MAXN]; 
const int base = 256;
const int MOD = 1e9 + 19972207; 
int p[MAXN]; 
int ip[MAXN]; 
int curHash[MAXN];
int revCurHash[MAXN];  

///++++++++++++++++++++++++++++++++++++++///

int mul(int a, int b){ 
    return (a * b) % MOD; 
}

int Pow(int a, int b) { 
    if (b == 0) return 1; 
    int tmp = Pow(a, b >> 1); 
    return (b & 1 ? mul(a, mul(tmp, tmp)) : mul(tmp, tmp)); 
}

int Div(int a, int b) {
    return mul(a, ip[b]); 
}

int add(int a, int b) {
    return ((a + b) % MOD + MOD) % MOD; 
}

void calc(int u, int p) { 
    sizeTree[u] = 1;
    for (int &v : g[u]) { 
        if (block[v] || v == p) continue; 
        calc(v, u); 
        sizeTree[u] += sizeTree[v];
    }
}

int FindCentroid(int u, int p, int SZ) { 
    for (int &v : g[u]) { 
        if (block[v] || v == p) continue; 
        if (sizeTree[v] > SZ) return FindCentroid(v, u, SZ);
    }
    return u;
}

void decompose(int u, int par) { 
    calc(u, 0); 
    int c = FindCentroid(u, 0, sizeTree[u] / 2);
    parent[c] = par; 
    block[c] = 1;
    for (int &v : g[u]) { 
        if (block[v]) continue;
        decompose(v, c);
    }
}

bool pushDown(int u, int par, int depth, int revLength, int aimLength, int blocked, unordered_map<int, bool> &marked, vector<int> &vecAdd) { 
    curHash[depth] = (curHash[depth - 1] + (intChar[u] * p[depth - 1])) % MOD; 
    revCurHash[depth] = (revCurHash[depth - 1] + (intChar[u] * p[revLength])) % MOD;
    if (depth >= aimLength) { 
        if (depth == aimLength) { 
            int revHash = Div(revCurHash[depth], revLength); 
            if (revHash == curHash[depth]) return true;  
        } else { 
            return false; 
        }
    } else { 
        int addHash = add(curHash[depth], -curHash[1]); 
        addHash = Div(addHash, 1); 
        vecAdd.push_back(addHash); 
        int leftLength = aimLength - depth; 
        if (depth >= leftLength) { 
            { 
                int Hash = curHash[depth - leftLength];
                int revHash = Div(revCurHash[depth - leftLength], revLength + leftLength);
                if (Hash == revHash) { 
                    int nowHash = add(curHash[depth], -curHash[depth - leftLength]); 
                    nowHash = Div(nowHash, depth - leftLength + 1); 
                    if (marked[nowHash]) return true; 
                }
            }
        } 
    }
    for (int &v : g[u]) { 
        if (v == par || v == blocked) continue; 
        bool good = pushDown(v, u, depth + 1, revLength - 1, aimLength, blocked, marked, vecAdd); 
        if (good) return true; 
    }
    return false; 
}

bool process(int midNode, int curLength) { 
    unordered_map<int, bool> marked; 
    curHash[1] = (intChar[midNode] * p[0]) % MOD; 
    revCurHash[1] = (intChar[midNode] * p[numNode]) % MOD;
    for (int &curNode : g[midNode]) { 
        if (curNode == parent[midNode]) continue; 
        vector<int> vecAdd; 
        bool good = pushDown(curNode, midNode, 2, numNode - 1, curLength, parent[midNode], marked, vecAdd); 
        if (good) return true; 
        for (int &nowHash : vecAdd) marked[nowHash] = true; 
        vecAdd.clear(); 
    }
    return false; 
}

bool lengthPalin(int curLength) {
    FOR(midNode, 1, numNode) { 
        bool found = process(midNode, curLength); 
        if (found) return true; 
    }
    return false; 
}

void solve() {
    cin >> numNode; 
    cin >> nodeChar;
    p[0] = 1; 
    FOR(i, 1, numNode) p[i] = (p[i - 1] * base) % MOD; 
    FOR(i, 0, numNode) ip[i] = Pow(p[i], MOD - 2);  
    FOR(i, 1, numNode) intChar[i] = nodeChar[i - 1] - 'a' + 1; 
    FOR(i, 1, numNode - 1) { 
        int u, v; cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    decompose(1, 0);
    int ans = 1; 
    {
        int lo = 0, hi = numNode / 2; 
        while (lo <= hi) { 
            int mid = (lo + hi) >> 1; 
            if (lengthPalin(2 * mid)) { 
                ans = max(ans, 2 * mid); 
                lo = mid + 1; 
            } else hi = mid - 1; 
        }
    }
    {
        int lo = 0, hi = numNode / 2; 
        while (lo <= hi) { 
            int mid = (lo + hi) >> 1; 
            if (lengthPalin(2 * mid + 1)) { 
                ans = max(ans, 2 * mid + 1); 
                lo = mid + 1; 
            } else hi = mid - 1; 
        }
    }
    cout << ans; 
}

///++++++++++++++++++++++++++++++++++++++///

#define task "COCI19_lampice"
int32_t main() {
    if (fopen(task".inp","r")) {
        freopen(task".inp","r",stdin);
        freopen(task".out","w",stdout);
    }
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    solve();
    bool M2;
    cerr << "++++++++++++++++++++++++++++\n";
    cerr << "Time: " << clock() << " ms" << '\n';
    cerr << "Memory: " << abs(&M2 - &M1) / 1024 / 1024 << " MB" << '\n';
    cerr << "++++++++++++++++++++++++++++\n";
    return 0;
}

Compilation message (stderr)

lampice.cpp: In function 'int32_t main()':
lampice.cpp:171:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  171 |         freopen(task".inp","r",stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
lampice.cpp:172:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  172 |         freopen(task".out","w",stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...