码迷,mamicode.com
首页 > 编程语言 > 详细

[XSY 1551] 往事 广义后缀数组

时间:2017-08-10 15:36:29      阅读:376      评论:0      收藏:0      [点我收藏+]

标签:include   lease   logs   tor   实现   getc   pre   iterator   合并   

题意

  给定一棵 n 个点的树, 每条边上有字符 c .

  定义 s[i] 为从 i 到根的所有字符组成的字符串.

  求 $\max_{1 \le u < v \le n} [ LCP(s[u], s[v]) + LCS(s[u], s[v]) ]$ .

  n <= 200000 .

 

实现1  n log^2 n 广义后缀数组 + 启发式合并

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cctype>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <set>
  9 using namespace std;
 10 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 11 #define P(i, a, b) for (register int i = (a); i >= (b); i--)
 12 #define LL unsigned long long
 13 
 14 namespace Input {
 15     const int S = 2000000;
 16     char s[S], *h = s+S, *t = h;
 17     inline char getchr(void) { if (h == t) fread(s, 1, S, stdin), h = s; return *h++; }
 18     inline int rd(void) {
 19         int f = 1; char c = getchr(); for (; !isdigit(c); c = getchr()) if (c == -) f = -1;
 20         int x = 0; for (; isdigit(c); c = getchr()) x = x*10+c-0; return x*f;
 21     }
 22 }
 23 using Input::rd;
 24 
 25 const int N = 200005;
 26 // remember to change back
 27 const int U = 20;
 28 const int M = 307;
 29 
 30 int n;
 31 vector<int> g[N];
 32 
 33 int u, dep[N];
 34 int par[U][N];
 35 LL p[N], Hash[U][N];
 36 
 37 void Build(void) {
 38     n = rd();
 39     u = (int)log2(n);
 40     p[0] = 1;
 41     F(i, 1, n) p[i] = p[i-1] * M;
 42     
 43     F(i, 2, n) {
 44         int f = rd(), c = rd() + 1;    // guaranteed that (empty = 0) < (0 + 1)
 45         g[f].push_back(i);
 46         dep[i] = dep[f] + 1;
 47         par[0][i] = f;
 48         Hash[0][i] = c;
 49     }
 50     
 51     F(i, 1, u) F(j, 1, n) {
 52         par[i][j] = par[i-1][par[i-1][j]];
 53         Hash[i][j] = Hash[i-1][j] * p[1 << (i-1)] + Hash[i-1][par[i-1][j]];
 54     }
 55 }
 56 
 57 int sa[N], rk[N], h[N];
 58 int Log2[N], Min[U][N];
 59 
 60 inline int cmp(int x, int y) {
 61     P(i, u, 0)
 62         if (dep[x] >= (1<<i) && dep[y] >= (1<<i) && Hash[i][x] == Hash[i][y])
 63             x = par[i][x], y = par[i][y];
 64     return Hash[0][x] < Hash[0][y];
 65 }
 66 inline int Get(int x, int y) {
 67     int Len = 0;
 68     P(i, u, 0)
 69         if (dep[x] >= (1<<i) && dep[y] >= (1<<i) && Hash[i][x] == Hash[i][y])
 70             x = par[i][x], y = par[i][y], Len += (1<<i);
 71     return Len;
 72 }
 73 inline int LCP(int x, int y) {
 74     // It‘s guaranteed that [x != y]
 75     if (x > y) swap(x, y);
 76     x++;
 77     int c = Log2[y - x + 1];
 78     return min(Min[c][y], Min[c][x + (1 << c) - 1]);
 79 }
 80 void Prework(void) {
 81     F(i, 1, n) sa[i] = i;
 82     sort(sa+1, sa+n+1, cmp);
 83     F(i, 1, n) rk[sa[i]] = i;
 84     
 85     F(i, 2, n)
 86         h[i] = Get(sa[i-1], sa[i]);
 87     
 88     F(i, 1, n)
 89         Log2[i] = (int)log2(i);
 90     
 91     F(i, 1, n) Min[0][i] = h[i];
 92     F(i, 1, u) F(j, 1, n)
 93         Min[i][j] = min(Min[i-1][j], Min[i-1][max(1, j - (1 << (i-1)))]);
 94 }
 95 
 96 set<int> s[N];
 97 int Max;
 98 
 99 inline void Merge(int x, int y) {
100     if (s[x].size() < s[y].size()) swap(s[x], s[y]);
101     for (set<int>::iterator it = s[y].begin(); it != s[y].end(); it++) {
102         // [ Insert ] and [ Find LCP with *it ]
103         s[x].insert(*it);
104         set<int>::iterator it2 = s[x].find(*it);
105         if (it2 != s[x].begin()) {
106             it2--;
107             Max = max(Max, dep[x] + LCP(*it2, *it));
108             it2++;
109         }
110         if (++it2 != s[x].end())
111             Max = max(Max, dep[x] + LCP(*it2, *it));
112     }
113     s[y].clear();    // release the non-use recollection
114 }
115 void Calc(int x) {
116     s[x].insert(rk[x]);
117     for (vector<int>::iterator it = g[x].begin(); it != g[x].end(); it++) {
118         Calc(*it);
119         Merge(x, *it);
120     }
121 }
122 
123 int main(void) {
124     #ifndef ONLINE_JUDGE
125         freopen("recollection.in", "r", stdin);
126     #endif
127     
128     Build();
129     Prework();
130     Calc(1); printf("%d\n", Max);
131     
132     return 0;
133 }

 

[XSY 1551] 往事 广义后缀数组

标签:include   lease   logs   tor   实现   getc   pre   iterator   合并   

原文地址:http://www.cnblogs.com/Sdchr/p/7339502.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!