POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
2016-10-25 21:33
465 查看
[b]Life Forms[/b]
[b]Description[/b]
You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, ears, eyebrows and the like. A few bear no human resemblance; these typically have geometric or amorphous shapes like cubes, oil slicks or clouds of dust.
The answer is given in the 146th episode of Star Trek - The Next Generation, titled The Chase. It turns out that in the vast majority of the quadrant's life forms ended up with a large fragment of common DNA.
Given the DNA sequences of several life forms represented as strings of letters, you are to find the longest substring that is shared by more than half of them.
[b]Input[/b]
Standard input contains several test cases. Each test case begins with 1 ≤ n ≤ 100, the number of life forms. n lines follow; each contains a string of lower case letters representing the DNA sequence of a life form. Each DNA sequence contains at least one and not more than 1000 letters. A line containing 0 follows the last test case.
[b]Output[/b]
For each test case, output the longest string or strings shared by more than half of the life forms. If there are many, output all of them in alphabetical order. If there is no solution with at least one letter, output "?". Leave an empty line between test cases.
[b]Sample Input[/b]
[b]Sample Output[/b]
[b]题意:[/b]
给你n个字符串,求出超过一半都包含的最长子串
[b]题解:[/b]
二分答案
将这n个串相连同样用一个没有出现过的字符间隔开来
只有两个相领的sa,lcp值是超过当前二分的md值并且 处于不同的串时才可当做两个数量
以此更新答案
[b]Description[/b]
You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, ears, eyebrows and the like. A few bear no human resemblance; these typically have geometric or amorphous shapes like cubes, oil slicks or clouds of dust.
The answer is given in the 146th episode of Star Trek - The Next Generation, titled The Chase. It turns out that in the vast majority of the quadrant's life forms ended up with a large fragment of common DNA.
Given the DNA sequences of several life forms represented as strings of letters, you are to find the longest substring that is shared by more than half of them.
[b]Input[/b]
Standard input contains several test cases. Each test case begins with 1 ≤ n ≤ 100, the number of life forms. n lines follow; each contains a string of lower case letters representing the DNA sequence of a life form. Each DNA sequence contains at least one and not more than 1000 letters. A line containing 0 follows the last test case.
[b]Output[/b]
For each test case, output the longest string or strings shared by more than half of the life forms. If there are many, output all of them in alphabetical order. If there is no solution with at least one letter, output "?". Leave an empty line between test cases.
[b]Sample Input[/b]
3 abcdefg bcdefgh cdefghi 3 xxx yyy zzz 0
[b]Sample Output[/b]
bcdefg cdefgh ?
[b]题意:[/b]
给你n个字符串,求出超过一半都包含的最长子串
[b]题解:[/b]
二分答案
将这n个串相连同样用一个没有出现过的字符间隔开来
只有两个相领的sa,lcp值是超过当前二分的md值并且 处于不同的串时才可当做两个数量
以此更新答案
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include<vector> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,int> #define MP make_pair typedef long long LL; const long long INF = 1e18+1LL; const double Pi = acos(-1.0); const int N = 2e5+10, M = 2e5+20, mod = 1e9+7, inf = 2e9; ///heght[i] 表示 Suffix(sa[i-1])和Suffix(sa[i]) 的最长公共前缀: ///rank[i] 表示 开头为i的后缀的等级: ///sa[i] 表示 排名为i的后缀 的开头位置: int *rank,r ,sa ,height ,wa ,wb ,wm ; bool cmp(int *r,int a,int b,int l) { return r[a] == r[b] && r[a+l] == r[b+l]; } void SA(int *r,int *sa,int n,int m) { int *x=wa,*y=wb,*t; for(int i=0;i<m;++i)wm[i]=0; for(int i=0;i<n;++i)wm[x[i]=r[i]]++; for(int i=1;i<m;++i)wm[i]+=wm[i-1]; for(int i=n-1;i>=0;--i)sa[--wm[x[i]]]=i; for(int i=0,j=1,p=0;p<n;j=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)wm[i]=0; for(i=0;i<n;++i)wm[x[y[i]]]++; for(i=1;i<m;++i)wm[i]+=wm[i-1]; for(i=n-1;i>=0;--i)sa[--wm[x[y[i]]]]=y[i]; for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;++i) { x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++; } } rank=x; } void Height(int *r,int *sa,int n) { for(int i=0,j=0,k=0;i<n;height[rank[i++]]=k) for(k?--k:0,j=sa[rank[i]-1];r[i+k] == r[j+k];++k); } int n,id ,all,pos ,vis ; vector<string > A; char str[101][1005]; int check(int len) { int i = 2, mx, mi,cnt = 0,flag; while(1) { while(i <= n && height[i]< len) i++; if(i > n) return 0; for(int j = 0; j < all; ++j) vis[j] = 0; cnt = 1; flag = id[sa[i-1]]; vis[flag] = 1; while(i <= n && height[i] >= len) { if(!vis[id[sa[i]]])cnt++; vis[id[sa[i]]] = 1; i++; } if(cnt > all/2) return 1; } return 0; } void Output (int len) { A.clear(); int i = 2,cnt = 0,flag,star; while(1) { while(i <= n && height[i] < len) i++; if(i > n) break; for(int j = 0; j < all; ++j) vis[j] = 0; cnt = 1; flag = id[sa[i-1]]; vis[flag] = 1; star = pos[sa[i-1]]; while(i <= n && height[i] >= len) { if(!vis[id[sa[i]]])cnt++; vis[id[sa[i]]] = 1; i++; } if(cnt > all/2) { string now = ""; for(int j = star; j <= star + len - 1; ++j) { now += str[flag][j]; } A.push_back(now); } } sort(A.begin(),A.end()); for(int i = 0; i < A.size(); ++i) cout<<A[i]<<endl; } int main() { while(scanf("%d",&n)!=EOF) { if(n == 0) break; for(int i = 0; i < n; ++i) scanf("%s",str[i]); all = n; int cnt = 0, rr = 0; for(int i = 0; i < n; ++i) { rr = max(rr,(int )strlen(str[i])); for(int j = 0; str[i][j] != '\0'; ++j) { id[cnt] = i; pos[cnt] = j; r[cnt++] = str[i][j] - 'a' + 1 + 100; } id[cnt] = i; r[cnt++] = i; } r[--cnt] = 0; n = cnt; SA(r,sa,n+1,300); Height(r,sa,n); // cout<<rr<<endl; int ll = 1, ans = 0; while(ll <= rr) { int md = (ll + rr) >> 1; if(check(md)) { ans = md, ll = md + 1; } else { rr = md - 1; } } if(ans == 0) puts("?\n"); else { Output(ans); printf("\n"); } } return 0; }
相关文章推荐
- POJ 3294 Life Forms (后缀数组,求出现在不少于k个字符串的最长子串)
- POJ 3294 Life Forms(不小于k个字符串中的最长子串 后缀数组)
- POJ 3294 Life Forms (后缀数组,求出现在不少于k个字符串的最长子串)
- poj 3294 求多于k个字符串的最长公共子串的个数-------后缀数组+二分答案
- 【POJ 3294】Life Forms 不小于k个字符串中的最长子串
- poj 3294 Life Forms(不小于k 个字符串中的最长子串)
- poj 3294 在K个字符串中出现最长公共子串
- poj 3294 不小于 k 个字符串中的最长子串(后缀数组+二分)
- POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)
- POJ 3294 出现在至少K个字符串中的子串
- POJ 3294 Life Forms(后缀数组求k个串的最长子串)
- POJ 3415 Life Forms 给定n个字符串,求出现在不小于k个字符串中的最长子串。
- POJ 3294 后缀数组:求不小于k个字符串中的最长子串
- poj 3294 Life Forms 求n(n>1)个字符串的最长的一个子串 后缀数组
- POJ 题目3294Life Forms(后缀数组求超过k个的串的最长公共子串)
- POJ3294 出现在至少k个字符串中的最长子串
- POJ 3294 二分找超过一半字符串中存在的子串
- poj 1743 后缀数组+二分答案 求一个串的最长无重叠的重复出现次数最多的子串
- poj 3294 后缀数组求至少在k个串中出现的公共子串
- POJ 3261Milk Patterns可重叠至少出现K次最长子串 二分+height分段