SPOJ220---Relevant Phrases of Annihilation(后缀数组+二分,对后缀分组)
2016-09-05 19:18
369 查看
题目
题意:给定N个串,求每个串至少出现两次的最长子串
思路:二分枚举长度,根据长度len分组,若某组里的个数>=k,则说明存在长度为len的至少重复k次子串。
题意:给定N个串,求每个串至少出现两次的最长子串
思路:二分枚举长度,根据长度len分组,若某组里的个数>=k,则说明存在长度为len的至少重复k次子串。
#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> using namespace std; const int MAXN = 110000; char s[MAXN]; int id[MAXN]; int sa[MAXN], rank[MAXN], height[MAXN], c[MAXN], tmp[MAXN]; int n, m, T; void makesa(int m) { memset(c, 0, m * sizeof(int)); for(int i = 0; i < n; ++i) ++c[rank[i] = s[i]]; for(int i = 1; i < m; ++i) c[i] += c[i - 1]; for(int i = 0; i < n; ++i) sa[--c[rank[i]]] = i; for(int k = 1; k < n; k <<= 1) { for(int i = 0; i < n; ++i) { int j = sa[i] - k; if(j < 0) j += n; tmp[c[rank[j]]++] = j; } int j = c[0] = sa[tmp[0]] = 0; for(int i = 1; i < n; ++i) { if(rank[tmp[i]] != rank[tmp[i - 1]] || rank[tmp[i] + k] != rank[tmp[i - 1] + k]) c[++j] = i; sa[tmp[i]] = j; } memcpy(rank, sa, n * sizeof(int)); memcpy(sa, tmp, n * sizeof(int)); } } void calheight() { for(int i = 0, k = 0; i < n; height[rank[i++]] = k) { k -= (k > 0); int j = sa[rank[i] - 1]; while(s[i + k] == s[j + k]) ++k; } } int mx[MAXN], mn[MAXN]; int stk[MAXN]; void update_max(int &a, int b) { if(a == -1 || a < b) a = b; } void update_min(int &a, int b) { if(a == -1 || a > b) a = b; } bool check(int L) { int sum = 0, top = 0; memset(mx, -1, m * sizeof(int)); memset(mn, -1, m * sizeof(int)); memset(c, 0, m * sizeof(int)); for(int i = 0; i < n; ++i) { if(height[i] >= L) { update_max(mx[id[sa[i]]], sa[i]); update_min(mn[id[sa[i]]], sa[i]); stk[++top] = id[sa[i]]; if(mx[id[sa[i]]] - mn[id[sa[i]]] >= L) { if(!c[id[sa[i]]]) ++sum; c[id[sa[i]]] = true; if(sum >= m) return true; } } else { sum = 0; while(top) { int t = stk[top--]; mx[t] = mn[t] = -1; c[t] = false; } update_max(mx[id[sa[i]]], sa[i]); update_min(mn[id[sa[i]]], sa[i]); stk[++top] = id[sa[i]]; } } return false; } int solve() { int l = 1, r = 5001; while(l < r) { int mid = (l + r) >> 1; if(check(mid)) l = mid + 1; else r = mid; } return l - 1; } int main() { scanf("%d", &T); while(T--) { scanf("%d", &m); n = 0; for(int i = 0; i < m; ++i) { scanf("%s", s + n); while(s ) id[n++] = i; s[n++] = i + 1; } s[n - 1] = 0; makesa(128); calheight(); printf("%d\n", solve()); } }
相关文章推荐
- SPOJ220---Relevant Phrases of Annihilation(后缀数组+二分,对后缀分组)
- [SPOJ220]PHRASES - Relevant Phrases of Annihilation(后缀数组+二分)
- 字符串练习题:SPOJ 220 Relevant Phrases of Annihilation(后缀数组加二分)
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分)
- spoj 220 Relevant Phrases of Annihilation (后缀数组 每个串中都至少出现两次的不重叠最长子串)
- 【SPOJ220】Relevant Phrases of Annihilation(后缀数组,二分)
- 【后缀数组】【spoj 220】Relevant Phrases of Annihilation
- spoj 220 Relevant Phrases of Annihilation(n个串的最长公共重复2次子串)
- spoj220 Relevant Phrases of Annihilation
- 【SPOJ】220 Relevant Phrases of Annihilation
- [spoj][220][Relevant Phrases of Annihilation]
- SPOJ 220 Relevant Phrases of Annihilation
- SPOJ220:Relevant Phrases of Annihilation(后缀数组)
- spoj 220 Relevant Phrases of Annihilation (后缀数组应用)
- spoj 220 Relevant Phrases of Annihilation(每个字符串至少出现两次且不重叠的最长子串)
- SPOJ 220 . Relevant Phrases of Annihilation(后缀数组)
- Relevant Phrases of Annihilation spoj220
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组)
- SPOJ 220 Relevant Phrases of Annihilation (后缀数组)