poj 3294 Life Forms
来源:互联网 发布:aframe.js 加载obj 编辑:程序博客网 时间:2024/06/10 18:40
题意
输入n个DNA序列,你的任务是求出一个长度最大的字符串,使得超过一半的DNA序列中连续出现。如果有多解,按照字典序从小到大输出所有解。
解法
这是一道经典的题目,解法有很多。首先用不同的分隔字符把所有输入的字符串连接在一起。求这个新串的后缀数组和height数组,然后二分答案,每次只需要判断是否有一个长度为p的串在超过一半的串中连续出现。方法是把height分为若干段,每当height小于p时开辟一个新段,每一段开头p个字符都相同。只要某一段中超过n/2个原串的后缀,p就满足条件。
代码
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAX = 110000;int s[MAX];char ss[MAX];bool mark[1010];int n, k, size;int sa[MAX],rank[MAX],height[MAX];int wa[MAX],wb[MAX],wv[MAX],ws[MAX];int len[1010],vis[1010],good[MAX];int cmp(int *r,int a,int b,int l) { return r[a] == r[b] && r[a+l] == r[b+l]; } void fun(int *r, int n, int m){ int i,j,p,*x = wa, *y = wb, *t; for(i = 0; i < m; i ++) ws[i] = 0; for(i = 0; i < n; i ++) ws[x[i] = r[i]] ++; for(i = 1; i < m; i ++) ws[i] += ws[i-1]; for(i = n-1; i >= 0; i --) sa[--ws[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 < n; i ++) wv[i] = x[y[i]]; for(i = 0; i < m; i ++) ws[i] = 0; for(i = 0; i < n; i ++) ws[wv[i]] ++; for(i = 1; i < m; i ++) ws[i] += ws[i-1]; for(i = n-1; i >= 0; i--) sa[--ws[wv[i]]] = y[i]; for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i ++) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++; } } void calheight(int *r, int n){ int i, j, k=0; for(int i=1; i<=n; i++) rank[sa[i]] = i; for(int i=0; i<n; i++){ if(k) k--; int j = sa[rank[i]-1]; while(r[i+k] == r[j+k]) k++; height[rank[i]] = k; } } bool check(int mid){memset(mark, false, sizeof(mark));int ans = 0, num = 0;for(int i=2; i<=k; i++){if(height[i] >= mid){for(int j=1; j<=size; j++){if(sa[i-1] > len[j-1] && sa[i-1] < len[j]){ans += mark[j] ? 0 : 1;mark[j] = 1;}if(sa[i] > len[j-1] && sa[i] < len[j]){ans += mark[j] ? 0 : 1;mark[j] = 1;}}}else{if(ans > (n >> 1))good[++num] = sa[i-1];ans = 0;memset(mark, false, sizeof(mark));}}if(ans > (n >> 1))good[++num] = sa[k];if(num){good[0] = num;return true;}return false;}int main(){int t = 0; while(scanf("%d",&n) == 1 && n){k = 0, size = 0,len[0] = -1;for(int i=0;i<n;++i){ scanf("%s",ss + k); for(;ss[k] != '\0';++k) s[k] = ss[k]; s[len[++size] = k++] = 300 + i; } s[k-1] = 0;fun(s, k, 400);calheight(s, k-1);if(t++) puts("");good[0] = 0;int l = 1, r = k;while(l <= r){int mid = (l + r) >> 1;if(check(mid)) l = mid + 1;else r = mid -1;}if(l == 1) puts("?");else{for(int i=1; i<=good[0]; i++){for(int j=good[i]; j<good[i]+l-1; j++)printf("%c",s[j]);puts("");}}}return 0;}
0 0
- poj 3294 Life Forms
- poj 3294 Life Forms
- Poj 3294 Life Forms
- poj 3294 Life Forms
- POJ-3294-Life Forms
- POJ 3294 Life Forms
- poj-3294-Life Forms
- POJ 3294 Life Forms
- POJ 3294 Life Forms
- POJ 3294 Life Forms
- POJ - 3294 Life Forms
- poj 3294 Life Forms
- POJ 3294 Life Forms
- POJ 3294 Life Forms
- POJ - 3294 Life Forms
- POJ 3294Life Forms
- AC解 - Life Forms(POJ#3294)
- poj 3294 Life Forms(后缀数组+二分)
- MQL4编程学习笔记(二)
- C++ 指定字面值的类型
- 输出螺旋矩阵
- Leetcode:Largest Number
- 致自己的一封信
- poj 3294 Life Forms
- 策略模式
- R语言从字符串中读取dataframe方法
- POJ 3083-Children of the Candy Corn(dfs+bfs)
- 案例说明stm32官方库函数使用方法 (库版本v3.5, Keil MDK 5)
- hdu 1050 Moving Tables(贪心)
- uva572
- poj 3087
- FastDFS