2754: [SCOI2012]喵星球上的点名
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2068 Solved: 907
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
6 8 25 0 24 14 8 6 18 0 10 20 24 0
7 14 17 8 7 0 17 0 5 8 25 0 24 0
4 8 25 0 24
4 7 0 17 0
4 17 0 8 25
Sample Output
2
1
0
1 2
【提示】
事实上样例给出的数据如果翻译成地球上的语言可以这样来看
2 3
izayoi sakuya
orihara izaya
izay
hara
raiz
HINT
【数据范围】
对于30%的数据,保证:
1<=N,M<=1000,喵星人的名字总长不超过4000,点名串的总长不超过2000。
对于100%的数据,保证:
1<=N<=20000,1<=M<=50000,喵星人的名字总长和点名串的总长分别不超过100000,保证喵星人的字符串中作为字符存在的数不超过10000。
Solution1
把名字和点名串用不同的字符连在一起,给对应名字的后缀打标记,做出后缀数组后,对于每个询问,找出其rank值,在sa中左右两边找,用一个数组统计答案即可。
这个东西是很暴力的,但是,数据很水,就可以水过了。
打的时候,把x设了值,又把x、y换了,调了很久。
Solution2
上面的做法是比较不稳定的,看数据,下面的做法则是稳定的O(nlogn)-----(十分感谢Semiwaker大佬的指导)。
我们可以发现,对于一个询问,那么它在sa数组中对应了一段可行的区间,需要统计这个区间内有多少个属于不同名字的后缀。
另外,我们也需要知道,属于同一个名字的后缀,被多少个区间所覆盖。
对于第一个问题,我们可以利用扫描线的方法来解决。对于每个名字所对应的后缀,我们只去计算它最后的那一个。但这个要怎么搞呢?
我们可以把所有的区间按右端点为第一关键字,左端点为第二关键字排序。假设当前遇到了一个后缀,我们就看同名字的后缀前面有没有出现过,如果没有,就直接在该位置+1;否则就把前面出现过的最后的那个后缀的位置-1,再在当前位置上+1。这个可以用一个树状数组来维护,遇到询问区间,只需要区间求和就好。
对于第二个问题,我们依然可以利用扫描线的方法来解决。对于每个名字所对应的的后缀,我们只计算它在该询问区间中,出现的最左的那一个就好。
我们可以把所有区间化为左端点+1、右端点-1。那么要如何统计呢?我们记录每一个名字当前出现的最迟的后缀的编号,再做一个区间求和就可以了,这个可以用树状数组来完成。
总的时间复杂度为O(nlogn),但似乎跑得比暴力还要慢,是我写得不好吗?
Code1
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <iostream> 7 #include <set> 8 9 using namespace std; 10 11 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i) 12 #define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i) 13 #define mset(a, b) memset(a, b, sizeof(a)) 14 const int maxn = 1000005; 15 int sa[maxn], h[maxn], rk[maxn], num[maxn]; 16 int w_a[maxn], w_b[maxn], w_v[maxn], w_s[maxn]; 17 int bel[maxn]; 18 struct Node 19 { 20 int len, start; 21 }d[maxn]; 22 int vis[maxn], ans[maxn]; 23 int temp[maxn], t_cnt; 24 25 bool cmp(int *x, int a, int b, int l) 26 { 27 return x[a+l] == x[b+l] && x[a] == x[b]; 28 } 29 30 void da(int n, int m) 31 { 32 int *x = w_a, *y = w_b, *t; t_cnt = 0; 33 REP(i, 1, n) x[i] = num[i]; 34 REP(i, 0, m) w_s[i] = 0; 35 REP(i, 1, n) w_s[x[i]] ++; 36 REP(i, 1, m) w_s[i] += w_s[i-1]; 37 DWN(i, n, 1) sa[w_s[x[i]] --] = i; 38 for (int j = 1, p = 0; p != n; m = p, j *= 2) 39 { 40 p = 0; 41 REP(i, n-j+1, n) 42 y[++p] = i; 43 REP(i, 1, n) 44 if (sa[i]-j > 0) 45 y[++p] = sa[i]-j; 46 REP(i, 1, n) w_v[i] = x[y[i]]; 47 REP(i, 0, m) w_s[i] = 0; 48 REP(i, 1, n) w_s[w_v[i]] ++; 49 REP(i, 1, m) w_s[i] += w_s[i-1]; 50 DWN(i, n, 1) sa[w_s[w_v[i]] --] = y[i]; 51 p = 1, t = x, x = y, y = t, x[sa[1]] = 1; //千万注意啊,不能把交换往后挪啊 52 REP(i, 2, n) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? p : ++p; 53 } 54 } 55 56 void calc_height(int n) 57 { 58 REP(i, 1, n) rk[sa[i]] = i; 59 int k = 0; 60 REP(i, 1, n) 61 { 62 if (k) k --; 63 int j = sa[rk[i]-1]; 64 while (num[i+k] == num[j+k] && i+k <= n && j+k <= n) k ++; 65 h[rk[i]] = k; 66 } 67 } 68 69 int main() 70 { 71 int len = 0, n, m, breaker = 10001; 72 scanf("%d %d", &n, &m); 73 REP(i, 1, n) 74 { 75 int l; 76 scanf("%d", &l); 77 REP(j, 1, l) 78 scanf("%d", &num[++len]), bel[len] = i, num[len] ++; 79 num[++len] = ++breaker; 80 scanf("%d", &l); 81 REP(j, 1, l) 82 scanf("%d", &num[++len]), bel[len] = i, num[len] ++; 83 num[++len] = ++breaker; 84 } 85 REP(i, 1, m) 86 { 87 scanf("%d", &d[i].len); 88 d[i].start = len+1; 89 REP(j, 1, d[i].len) 90 scanf("%d", &num[++len]), num[len] ++; 91 num[++len] = ++breaker; 92 } 93 da(len, breaker); 94 calc_height(len); 95 REP(i, 1, m) 96 { 97 int l = rk[d[i].start], r = rk[d[i].start], now_l = d[i].len; 98 while (l >= 2 && min(h[l], now_l) >= d[i].len) 99 now_l = min(now_l, h[l]), l --; 100 now_l = len; 101 while (r+1 <= n && min(now_l, h[r+1]) >= d[i].len) 102 r ++, now_l = min(now_l, h[r]); 103 int cnt = 0; 104 REP(j, l, r) 105 if (vis[bel[sa[j]]] != i && bel[sa[j]] != 0) 106 { 107 vis[bel[sa[j]]] = i; 108 cnt ++; 109 ans[bel[sa[j]]] ++; 110 } 111 printf("%d ", cnt); 112 } 113 REP(i, 1, n) 114 printf("%d%c", ans[i], i == n ? ' ' : ' '); 115 return 0; 116 }
Code2
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <cmath> 7 #include <vector> 8 9 using namespace std; 10 11 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i) 12 #define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i) 13 #define mset(a, b) memset(a, b, sizeof(a)) 14 const int maxn = 300005; 15 int n, m, bel[maxn], num[maxn]; 16 int w_a[maxn], w_b[maxn], w_v[maxn], w_s[maxn], sa[maxn], rk[maxn], h[maxn], st[maxn][21]; 17 struct Node 18 { 19 int len, start, l, r, id; 20 bool operator < (const Node &AI) const { return r == AI.r ? l < AI.l : r < AI.r; } 21 }query[maxn]; 22 int c[maxn], las[maxn], ans1[maxn], ans2[maxn], add[maxn]; 23 vector <int> del[maxn]; 24 25 bool cmp(int *x, int a, int b, int l) { return x[a] == x[b] && x[a+l] == x[b+l]; } 26 27 void get_sa(int n, int m) 28 { 29 int *x = w_a, *y = w_b, *t; 30 REP(i, 0, m) w_s[i] = 0; 31 REP(i, 1, n) w_s[x[i]=num[i]] ++; 32 REP(i, 1, m) w_s[i] += w_s[i-1]; 33 DWN(i, n, 1) sa[w_s[x[i]]--] = i; 34 for (int j = 1, p = 0; p != n; j *= 2, m = p) 35 { 36 p = 0; 37 REP(i, n-j+1, n) y[++p] = i; 38 REP(i, 1, n) if (sa[i]-j > 0) y[++p] = sa[i]-j; 39 REP(i, 1, n) w_v[i] = x[y[i]]; 40 REP(i, 0, m) w_s[i] = 0; 41 REP(i, 1, n) w_s[w_v[i]] ++; 42 REP(i, 1, m) w_s[i] += w_s[i-1]; 43 DWN(i, n, 1) sa[w_s[w_v[i]]--] = y[i]; 44 t = x, x = y, y = t, p = 1, x[sa[1]] = 1; 45 REP(i, 2, n) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? p : ++p; 46 } 47 } 48 49 void get_h(int n) 50 { 51 REP(i, 1, n) rk[sa[i]] = i; 52 int k = 0; 53 REP(i, 1, n) 54 { 55 if (k) k --; 56 int j = sa[rk[i]-1]; 57 while (num[i+k] == num[j+k] && i+k <= n && j+k <= n) k ++; 58 h[rk[i]] = k; 59 } 60 REP(i, 1, n) st[i][0] = h[i]; 61 REP(j, 1, 20) 62 REP(i, 1, n) 63 if (i+(1<<(j-1)) <= n)//必须判断,不然会RE 64 st[i][j] = min(st[i][j-1], st[i+(1<<(j-1))][j-1]); 65 } 66 67 int calc(int l, int r) 68 { 69 l ++; 70 int k = int(log2(r-l+1)); 71 return min(st[l][k], st[r-(1<<k)+1][k]); 72 } 73 74 int lowbit(int x) { return x & -x; } 75 76 void c_modify(const int &n, int x, int d) { while (x <= n) c[x] += d, x += lowbit(x); } 77 78 int c_query(const int &n, int x) 79 { 80 int ret = 0; 81 while (x > 0) ret += c[x], x -= lowbit(x); 82 return ret; 83 } 84 85 int main() 86 { 87 scanf("%d %d", &n, &m); 88 int breaker = 10000, len = 0; 89 REP(i, 1, n) 90 { 91 int l; 92 scanf("%d", &l); 93 REP(j, 1, l) scanf("%d", &num[++len]), bel[len] = i, num[len] ++; 94 num[++len] = ++breaker; 95 scanf("%d", &l); 96 REP(j, 1, l) scanf("%d", &num[++len]), bel[len] = i, num[len] ++; 97 num[++len] = ++breaker; 98 } 99 REP(i, 1, m) 100 { 101 scanf("%d", &query[i].len), query[i].id = i; 102 query[i].start = len+1; 103 REP(j, 1, query[i].len) scanf("%d", &num[++len]), num[len] ++; 104 num[++len] = ++breaker; 105 } 106 get_sa(len, breaker), get_h(len); 107 REP(i, 1, m) 108 { 109 int k = rk[query[i].start], l = 1, r = k; 110 query[i].l = query[i].r = k; 111 while (l <= r) 112 { 113 int mid = (l+r)>>1; 114 if (calc(mid, k) >= query[i].len) query[i].l = mid, r = mid-1; 115 else l = mid+1; 116 } 117 l = k+1, r = len; 118 while (l <= r) 119 { 120 int mid = (l+r)>>1; 121 if (calc(k, mid) >= query[i].len) query[i].r = mid, l = mid+1; 122 else r = mid-1; 123 } 124 } 125 sort(query+1, query+m+1); 126 int now = 1; 127 REP(i, 1, len) 128 { 129 int k = sa[i]; 130 if (bel[k] != 0) 131 { 132 if (las[bel[k]] != 0) c_modify(len, las[bel[k]], -1); 133 las[bel[k]] = i, c_modify(len, i, 1); 134 } 135 while (query[now].r == i && now <= m) 136 ans1[query[now].id] = c_query(len, i)-c_query(len, query[now].l-1), now ++; 137 } 138 mset(c, 0), mset(las, 0); 139 REP(i, 1, m) add[query[i].l] ++, del[query[i].r+1].push_back(query[i].l); 140 REP(i, 1, len) 141 { 142 int k = sa[i]; 143 c_modify(len, i, add[i]); 144 REP(j, 0, del[i].size()-1) c_modify(len, del[i][j], -1);//这段尤为注意,必须一边做一边删 145 //否则,就会出现减出负数的情况 146 if (bel[k] != 0) 147 { 148 if (las[bel[k]] != 0) ans2[bel[k]] -= c_query(len, las[bel[k]]); 149 ans2[bel[k]] += c_query(len, i), las[bel[k]] = i; 150 } 151 } 152 REP(i, 1, m) printf("%d ", ans1[i]); 153 REP(i, 1, n) printf("%d%c", ans2[i], i == n ? ' ' : ' '); 154 return 0; 155 }