Advertisement
dgc9715

Lampice

Dec 14th, 2019
412
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.79 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #ifdef DGC
  6. #include "debug.h"
  7. #else
  8. #define debug(...) 9715
  9. #endif
  10. typedef long long ll;
  11. typedef long double ld;
  12. typedef complex<ld> point;
  13. #define F first
  14. #define S second
  15.  
  16. typedef pair<int, int> Hash;
  17. const int mod1 = 1e9+7, mod2 = 1e9+9, b1 = 31, b2 = 37;
  18.  
  19. Hash operator+(Hash lhs, const Hash &rhs)
  20. {
  21.     lhs.F += rhs.F;
  22.     if (lhs.F >= mod1) lhs.F -= mod1;
  23.     lhs.S += rhs.S;
  24.     if (lhs.S >= mod2) lhs.S -= mod2;
  25.     return lhs;
  26. }
  27.  
  28. Hash operator-(Hash lhs, const Hash &rhs)
  29. {
  30.     lhs.F += mod1 - rhs.F;
  31.     if (lhs.F >= mod1) lhs.F -= mod1;
  32.     lhs.S += mod2 - rhs.S;
  33.     if (lhs.S >= mod2) lhs.S -= mod2;
  34.     return lhs;
  35. }
  36.  
  37. Hash operator*(Hash lhs, const Hash &rhs)
  38. {
  39.     lhs.F = (ll)lhs.F * rhs.F % mod1;
  40.     lhs.S = (ll)lhs.S * rhs.S % mod2;
  41.     return lhs;
  42. }
  43.  
  44. const int N = 5e4 + 2;
  45. Hash B[N];
  46.  
  47. inline ll Get(const Hash &h)
  48. {
  49.     return ((ll)h.F) << 32 | h.S;
  50. }
  51.  
  52. struct centroid_decomposition
  53. {
  54.     int n;
  55.     string ids;
  56.     vector<bool> del;
  57.     vector<vector<int>> adj;
  58.     vector<int> size, parent;
  59.     vector<vector<pair<pair<Hash, Hash>, int>>> hs;
  60.  
  61.     centroid_decomposition(int n) : n(n), del(n), adj(n), size(n), parent(n) {};
  62.  
  63.     void add_edge(int u, int v)
  64.     {
  65.         adj[u].push_back(v);
  66.         adj[v].push_back(u);
  67.     }
  68.  
  69.     int centroid(int u)
  70.     {
  71.         vector<int> seen = {u};
  72.         parent[u] = -1;
  73.  
  74.         for (size_t i = 0; i < seen.size(); ++i)
  75.         {
  76.             u = seen[i];
  77.             for (int v : adj[u])
  78.                 if (!del[v] && v != parent[u])
  79.                     parent[v] = u, seen.push_back(v);
  80.         }
  81.  
  82.         for (int sz = seen.size(), i = sz - 1, mx = 0; i >= 0; --i, mx = 0)
  83.         {
  84.             size[u = seen[i]] = 1;
  85.             for (int v : adj[u])
  86.                 if (!del[v] && v != parent[u])
  87.                     size[u] += size[v], mx = max(mx, size[v]);
  88.             if (max(sz - size[u], mx) <= sz / 2)
  89.                 return u;
  90.         }
  91.  
  92.         return -1;
  93.     }
  94.  
  95.     void dfs(int u, int p, int d, Hash up, Hash down, vector<pair<pair<Hash, Hash>, int>> &h)
  96.     {
  97.         up = up * B[1] + Hash((ids[u] - 'a'), (ids[u] - 'a'));
  98.         down = down + Hash((ids[u] - 'a'), (ids[u] - 'a')) * B[d];
  99.         h.push_back({ { up, down }, d+1 });
  100.         for (int v : adj[u])
  101.             if (!del[v] && v != p)
  102.                 dfs(v, u, d + 1, up, down, h);
  103.     }
  104.  
  105.     bool check(int c, int len)
  106.     {
  107.         set<pair<ll, int>> mp;
  108.         for (auto &h : hs)
  109.         {
  110.             for (auto &i : h)
  111.                 if (len-i.S >= 0 && mp.find({ Get(i.F.F - i.F.S * B[len-i.S]), len-i.S }) != mp.end())
  112.                     return true;
  113.  
  114.             for (auto &i : h)
  115.             {
  116.                 auto up = i.F.F;
  117.                 auto down = i.F.S;
  118.                 down = down * B[1] + Hash((ids[c] - 'a'), (ids[c] - 'a'));
  119.                 up = up + Hash((ids[c] - 'a'), (ids[c] - 'a')) * B[i.S];
  120.                 if (up == down && i.S + 1 >= len) return true;
  121.                 if (len-i.S-1 >= 0)
  122.                     mp.insert({ Get(up - down * B[len - i.S - 1]), i.S + 1 });
  123.             }
  124.         }
  125.         return false;
  126.     }
  127.  
  128.     int rootify(int r)
  129.     {
  130.         int c = centroid(r);
  131.         assert(c != -1);
  132.         del[c] = true;
  133.  
  134.         hs.clear();
  135.         for (int v : adj[c])
  136.             if (!del[v])
  137.             {
  138.                 hs.emplace_back();
  139.                 dfs(v, c, 0, Hash(0, 0), Hash(0, 0), hs.back());
  140.             }
  141.  
  142.         int lo = 2, hi = n;
  143.         while (hi - lo > 3)
  144.         {
  145.             int md = (lo + hi + 1) >> 1;
  146.             if (check(c, md) || check(c, md+1))
  147.                 lo = md;
  148.             else
  149.                 hi = md - 1;
  150.         }
  151.  
  152.         int ret = 1;
  153.         for (; hi >= lo; --hi)
  154.             if (check(c, hi))
  155.             {
  156.                 ret = hi;
  157.                 break;
  158.             }
  159.  
  160.         for (int v : adj[c])
  161.             if (!del[v])
  162.                 ret = max(ret, rootify(v));
  163.  
  164.         return ret;
  165.     }
  166. };
  167.  
  168. int main()
  169. {
  170.     #ifdef DGC
  171.         freopen("a.in", "r", stdin);
  172.         //freopen("b.out", "w", stdout);
  173.     #endif
  174.  
  175.     ios_base::sync_with_stdio(0), cin.tie(0);
  176.  
  177.     int n;
  178.     cin >> n;
  179.     B[0] = make_pair(1, 1);
  180.     for (int i = 1; i <= n; ++i)
  181.         B[i] = B[i-1] * Hash(b1, b2);
  182.  
  183.     centroid_decomposition cd(n);
  184.     cin >> cd.ids;
  185.     for (auto &i : cd.ids) i += 1;
  186.     for (int u, v, i = 1; i < n; ++i)
  187.     {
  188.         cin >> u >> v;
  189.         --u, --v;
  190.         cd.add_edge(u, v);
  191.     }
  192.  
  193.     cout << cd.rootify(0) << "\n";
  194.  
  195.     return 0;
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement