Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 33462 | Accepted: 11124 |
Description數組
Inputapp
Outputcomposer
Sample Inputthis
30 25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18 82 78 74 70 66 67 64 60 65 80 0
Sample Outputspa
5
Hintcode
Sourceblog
題目大意:ip
給出一個長度爲$n$的序列,讓你找出最長的類似子串。這裏類似定義爲兩個串每次字符對應的差值相同ci
Sol:
很顯然,咱們能夠對原序列進行差分,這樣若是在原序列中長度爲$n$的互不相交的相同的字符串,那麼答案爲$n + 1$字符串
這是一個經典的問題。首先二分答案,而後對$height$數組分組,若$sa[i] - sa[j] > ans$那麼能夠更新答案
#include<cstdio> #include<algorithm> using namespace std; const int MAXN = 1e5 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N; int s[MAXN], sa[MAXN], rak[MAXN], tp[MAXN], tax[MAXN], height[MAXN], P, M; void Qsort() { for(int i = 0; i <= M; i++) tax[i] = 0; for(int i = 1; i <= N; i++) tax[rak[i]]++; for(int i = 1; i <= M; i++) tax[i] += tax[i - 1]; for(int i = N; i >= 1; i--) sa[ tax[rak[tp[i]]]-- ] = tp[i]; } void SuffixSort() { M = 233; for(int i = 1; i <= N; i++) rak[i] = s[i], tp[i] = i; Qsort(); for(int w = 1, p = 0; p < N; M = p, w <<= 1) { p = 0; for(int i = 1; i <= w; i++) tp[++p] = N - i + 1; for(int i = 1; i <= N; i++) if(sa[i] > w) tp[++p] = sa[i] - w; Qsort(); swap(tp, rak); rak[sa[1]] = p = 1; for(int i = 2; i <= N; i++) rak[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? p : ++p; } int j = 0, k = 0; for(int i = 1; i <= N; i++) { if(k) k--; int j = sa[rak[i] - 1]; while(s[i + k] == s[j + k]) k++; height[rak[i]] = k; } //for(int i = 1; i <= N; i++) printf("%d ", sa[i]); puts(""); } bool check(int len) { int mx = sa[1], mi = sa[1]; for(int i = 2; i <= N; i++) { if(height[i] >= len - 1) mx = max(sa[i], mx), mi = min(sa[i], mi); else mx = mi = sa[i]; if(mx - mi >= len) return 1; } return 0; } int solve() { int l = 0, r = N, ans = 0; while(l <= r) { int mid = l + r >> 1; if(check(mid)) l = mid + 1, ans = mid; else r = mid - 1; } return ans; } int main() { while(scanf("%d", &N) && N != 0) { for(int i = 1; i <= N; i++) s[i] = read(); for(int i = N; i >= 1; i--) s[i] -= s[i - 1] - 100; SuffixSort(); int ans = solve(); if(ans >= 5) printf("%d\n", ans); else printf("%d\n", 0); } return 0; } /* 30 25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18 82 78 74 70 66 67 64 60 65 80 0 */