[HDU 5558] Alice's Classified Message (后缀数组+LCP+单调栈)
2016-10-12 23:39
399 查看
链接
HDU 5558题意
题意较复杂,可看原题。基本上等同于对一个字符串的若干个位置i求其前方位置j(0 <= j < i)的后缀suf(j)和suf(i)的LCP,多个答案输出最小j。
题解
裸的后缀数组+LCP问题,我加了一个单调栈优化常数。代码
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> using namespace std; #define maxn (1000010) bool cmp(int *r, int a, int b, int l) { return r[a] == r[b] && r[a + l] == r[b + l]; } int ta[maxn], tb[maxn], bk[maxn]; void da(int *r, int *sa, int n, int m) { int i, j, p, *x = ta, *y = tb, *t; for(i = 0; i < m; i++) bk[i] = 0; for(i = 0; i < n; i++) bk[x[i] = r[i]]++; for(i = 1; i < m; i++) bk[i] += bk[i-1]; for(i = 0; i < n; i++) sa[--bk[x[i]]] = i; for(j = 1, p = 1; p < n; j *= 2, m = p) { for(p = 0, i = n - j; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = 0; i < m; i++) bk[i] = 0; for(i = 0; i < n; i++) bk[x[i]]++; for(i = 1; i < m; i++) bk[i] += bk[i-1]; for(i = n-1; i >= 0; i--) sa[--bk[x[y[i]]]] = y[i]; for(t = x, x = y, y = t, x[sa[0]] = 0, p = 1, i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++; } } #define rank rrank int rank[maxn], sa[maxn], height[maxn]; void calheight(int *r, int n) { for(int i = 0; i < n; i++) rank[sa[i]] = i; for(int k = 0, i = 0; i < n; i++) { k ? k-- : 0; if(rank[i] > 0) while(r[i + k] == r[sa[rank[i] - 1] + k]) k++; height[rank[i]] = k; } } #define log2 Log2 int log2[maxn], st[maxn][32]; void st_prepare(int arr[], int n) { log2[1] = 0; for(int i = 2; i <= n; i++) { log2[i] = log2[i-1]; if((1 << log2[i] + 1) == i) log2[i]++; } for(int i = n-1; i >= 0; i--) { st[i][0] = arr[i]; for(int j = 1; i + (1 << j) - 1 < n; j++) { st[i][j] = min(st[i][j-1], st[i + (1 << j-1)][j-1]); } } } int st_query(int l, int r) { int k = log2[r - l + 1]; return min(st[l][k], st[r - (1 << k) + 1][k]); } char in[maxn]; int r[maxn], n, left_next[maxn], right_next[maxn], _top; pair<int, int> _stack[maxn]; inline void _push_stack(int x[], int w, int p) { while(_top > 0) { if(w < _stack[_top].first) _top--; else break; } if(!_top) x[p] = -1; else x[p] = _stack[_top].second; _stack[++_top] = make_pair(w, p); } int T[maxn], K[maxn]; int main() { int t, kase = 0; cin >> t; while(t--) { scanf("%s", in); for(n = 0; in ; n++) r = in - 'a' + 1; r[n++] = 0; da(r, sa, n, 27); calheight(r, n); st_prepare(height, n); _top = 0; for(int i = 1; i < n; i++) _push_stack(left_next, sa[i], i); _top = 0; for(int i = n-1; i > 0; i--) _push_stack(right_next, sa[i], i); printf("Case #%d:\n", ++kase); printf("%d %d\n", -1, int(in[0])); int i = 1, j, K, T, rk; while(i < n-1) { K = 0, T = -1; rk = rank[i]; j = rk; while(left_next[j] != -1) { j = left_next[j]; int lcp = st_query(j+1, rk); if(lcp < K) break; if(lcp > K || lcp == K && sa[j] < T) K = lcp, T = sa[j]; } j = rk; while(right_next[j] != -1) { j = right_next[j]; int lcp = st_query(rk+1, j); if(lcp < K) break; if(lcp > K || lcp == K && sa[j] < T) K = lcp, T = sa[j]; } printf("%d %d\n", K ? K : -1, K ? T : int(in[i])); i += (K ? K : 1); } } return 0; }
相关文章推荐
- HDU 5558 Alice's Classified Message 后缀自动机
- HDU 5558 Alice's Classified Message(后缀自动机)
- hdu 5558 Alice's Classified Message(后缀数组)
- Hdu 5558 Alice's Classified Message(后缀数组,每个点的前面点和它匹配的最长长度)
- HDU - 5558 Alice's Classified Message
- HDU 5558 Alice's Classified Message (后缀自动机水题) 2015年合肥区域赛G题
- HDU-5558-Alice's Classified Message
- HDU - 3410 Passing the Message ——单调栈
- hdu5558 Alice's Classified Message (后缀数组)
- hdu5558 Alice's Classified Message
- HDU - 3410 Passing the Message(单调栈)
- 文章标题 HDU 3410 : Passing the Message (单调栈)
- HDU 3410 Passing the Message (单调栈)
- HDU 1505 City Game (单调栈+最大子矩阵面积)
- HDU 4122 Alice's mooncake shop(RMQ:动态最值)
- HDU 5558 2015ICPC合肥站G题
- HDU 3660 Alice and Bob's Trip
- 贪心+multiset · HDU - 4268 ·Alice and Bob
- 11年福州 B 单调栈 HDU 4122
- hdu 4111 Alice and Bob(中档博弈题)