您的位置:首页 > 其它

SDOI2008 Sandy的卡片( 后缀数组 )

2016-01-16 20:42 375 查看
求出后缀数组, 然后二分答案, 对height数组分组检验答案. 时间复杂度O(|S| log|S|)

--------------------------------------------------------------------------------

#include<cstdio>#include<cctype>#include<cstring>#include<algorithm> using namespace std; const int maxn = 1009;const int maxN = 1000009; inline int read() { char c = getchar(); for(; !isdigit(c); c = getchar()); int ret = 0; for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0'; return ret;} bool vis[maxn];int str[maxn][maxn], len[maxn], n, Top;int S[maxN], Id[maxN], stk[maxN], N;int cnt[maxN], Sa[maxN], Height[maxN], Rank[maxN]; void Build(int m) { int *x = Height, *y = Rank; for(int i = 0; i < m; i++) cnt[i] = 0; for(int i = 0; i < N; i++) cnt[x[i] = S[i]]++; for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1]; for(int i = N; i--; ) Sa[--cnt[x[i]]] = i; for(int k = 1, p = 0; k <= N; k <<= 1, p = 0) { for(int i = N - k; i < N; i++) y[p++] = i; for(int i = 0; i < N; i++) if(Sa[i] >= k) y[p++] = Sa[i] - k; for(int i = 0; i < m; i++) cnt[i] = 0; for(int i = 0; i < N; i++) cnt[x[y[i]]]++; for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1]; for(int i = N; i--; ) Sa[--cnt[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[Sa[0]] = 0; for(int i = 1; i < N; i++) { if(y[Sa[i]] != y[Sa[i - 1]] || y[Sa[i] + k] != y[Sa[i - 1] + k]) p++; x[Sa[i]] = p - 1; } if(p >= N) break; m = p; } for(int i = 0; i < N; i++) Rank[Sa[i]] = i; Height[0] = 0; for(int i = 0, h = 0; i < N; i++) if(Rank[i]) { if(h) h--; while(S[i + h] == S[Sa[Rank[i] - 1] + h]) h++; Height[Rank[i]] = h; }} void Init() { int mn = 1 << 30, mx = -1 << 30; n = read(); for(int i = 0; i < n; i++) { len[i] = read(); for(int j = 0; j < len[i]; j++) str[i][j] = read(); for(int j = len[i]; --j; ) { str[i][j] -= str[i][j - 1]; mn = min(mn, str[i][j]); mx = max(mx, str[i][j]); } } N = 0; for(int i = 0; i < n; i++) { for(int j = 1; j < len[i]; j++) { S
= str[i][j] - mn + n; Id[N++] = i; } S
= n - i - 1; Id[N++] = n; } Build(mx - mn + n + 1); memset(vis, 0, sizeof vis); vis
= 1; Top = 0;} bool chk(int v) { while(Top) vis[stk[--Top]] = 0; for(int i = 1; i < N; i++) if(Height[i] >= v) { if(!vis[Id[Sa[i - 1]]]) vis[stk[Top++] = Id[Sa[i - 1]]] = 1; if(!vis[Id[Sa[i]]]) vis[stk[Top++] = Id[Sa[i]]] = 1; if(Top >= n) return true; } else { while(Top) vis[stk[--Top]] = 0; } return false;} void Work() { int l = 1, r = maxN, ans = 0; while(l <= r) { int m = (l + r) >> 1; if(chk(m)) { ans = m, l = m + 1; } else r = m - 1; } printf("%d\n", ++ans);} int main() { Init(); Work(); return 0;}--------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: