Submission #848932

#TimeUsernameProblemLanguageResultExecution timeMemory
848932qthang2k11Lampice (COCI19_lampice)C++17
110 / 110
2439 ms11700 KiB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

const int N = 5e4 + 5, mod = 1e9 + 7, base = 31;
unordered_set<int> mp, existed;
int xuoi[N], nguoc[N], pw[N];
int dpt[N], up[N], sz[N];
bool rem[N], checked;
vector <int> adj[N];
int ans = 1, n, r;
char a[N];

int add(int value, char x) {
   return (value * base + x - 'a' + 1);
}

int dfs(int x, int p) {
   sz[x] = 1;
   for (int y: adj[x]) {
      if (y == p || rem[y]) continue;
      sz[x] += dfs(y, x);
   }

   return sz[x];
}

void down(int x, int p, int len) {
   dpt[x] = dpt[p] + 1;
   up[dpt[x]] = x;
   if (dpt[x] >= len || checked) return;
   int curlen = dpt[x] + 1;
   if (curlen == len) {
      ///centroid->con
      ///xuoi == nguoc
      int Xuoi = xuoi[x] + (a[r] - 'a' + 1) * pw[dpt[x]];
      int Nguoc = nguoc[x] * base + (a[r] - 'a' + 1);
      if (Xuoi == Nguoc) return checked = 1, void();
   }
   mp.insert(xuoi[x]);
   for (int y: adj[x]) {
      if (y == p || rem[y]) continue;
      xuoi[y] = add(xuoi[x], a[y]);
      nguoc[y] = nguoc[x] + (a[y] - 'a' + 1) * pw[dpt[x]];
      down(y, x, len);
   }
   if (checked) return;
   if (curlen >= (len + 1) / 2) {
      int xx = len - curlen;
      if (xx <= curlen) {
         ///curstr[curlen-1,...,curlen-x]..curstr
         if (xx > dpt[x]) return;
         int chaxet = up[dpt[x] - xx]; //jump(x,xx);///log
         int Xuoi = xuoi[chaxet] + (a[r] - 'a' + 1) * pw[dpt[chaxet]];
         int Nguoc = nguoc[chaxet] * base + (a[r] - 'a' + 1);
         if (Xuoi != Nguoc) return;
         int suffix = xuoi[x] - xuoi[chaxet] * pw[xx];
         if (existed.find(suffix) != existed.end())
            return checked = 1, void();
      }
   }
}

bool ok(int x, int len) {
   if (sz[x] < len) return 0;
   if (len <= 1) return 1;
   dpt[x] = 0;
   xuoi[x] = nguoc[x] = 0;
   r = x;
   existed.clear();
   checked = 0;
   for (int y: adj[x]) {
      if (rem[y]) continue;
      mp.clear();
      xuoi[y] = nguoc[y] = a[y] - 'a' + 1;
      down(y, x, len);
      for (int x: mp)
         existed.insert(x);
   }
   return checked;
}

void sus(int x, int p) {
   sz[x] = 1;
   for (int y: adj[x]) {
      if (y == p || rem[y]) continue;
      sus(y, x);
      sz[x] += sz[y];
   }
}

void solve(int x) {
   {
      ///chan
      int l = ans / 2, r = sz[x];
      while (l <= r) {
         int mid = (l + r) / 2;
         if (ok(x, mid * 2)) {
            ans = max(ans, mid * 2);
            l = mid + 1;
         } else r = mid - 1;
      }
   }
   {
      ///le
      int l = ans / 2, r = sz[x];
      while (l <= r) {
         int mid = (l + r) / 2;
         if (ok(x, mid * 2 + 1)) {
            ans = max(ans, mid * 2 + 1);
            l = mid + 1;
         } else r = mid - 1;
      }
   }
   reverse(adj[x].begin(), adj[x].end());
}

int find_centroid(int x, int p, int tot) {
   for (int y: adj[x])
      if (y != p && !rem[y] && sz[y] > tot / 2)
         return find_centroid(y, x, tot);
   return x;
}

void build(int x = 1) {
   int c = find_centroid(x, 0, dfs(x, 0));
   rem[c] = 1;
   sus(c, 0);
   solve(c);
   solve(c);
   for (int y: adj[c])
      if (!rem[y])
         build(y);
}

int32_t main() {
   cin.tie(0)->sync_with_stdio(0);
   cin >> n;
   pw[0] = 1;
   for (int i = 1; i <= n; i++) pw[i] = 1ll * pw[i - 1] * base;
   for (int i = 1; i <= n; i++) cin >> a[i];
   for (int i = 1; i < n; i++) {
      int x, y;
      cin >> x >> y;
      adj[x].push_back(y);
      adj[y].push_back(x);
   }
   build();
   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...