POJ - 3294 Life Forms
2016-08-02 00:00
204 查看
1.题面
http://poj.org/problem?id=32942.题意
给你n个字符串,希望你求出一个长度最长的子串s,s在至少n/2个字符串中出现过,3.思路
将所有的数字连在一起后使用后缀数组,二分答案第二种方法也是先用后缀数组处理,后面使用一个尺取法
二分 800+ms
尺取法 1200+ms
我觉得set的常数产生了很大的影响
4.代码
二分代码/***************************************************************** > File Name: Cpp_Acm.cpp > Author: Uncle_Sugar > Mail: uncle_sugar@qq.com > Created Time: 2016年08月01日 星期一 18时50分27秒 *****************************************************************/ # include <cstdio> # include <cstring> # include <cctype> # include <cmath> # include <cstdlib> # include <climits> # include <iostream> # include <iomanip> # include <set> # include <map> # include <vector> # include <stack> # include <queue> # include <algorithm> using namespace std; # define rep(i,a,b) for (i=a;i<=b;i++) # define rrep(i,a,b) for (i=b;i>=a;i--) template<class T>void PrintArray(T* first,T* last,char delim=' '){ for (;first!=last;first++) cout << *first << (first+1==last?'\n':delim); } const int debug = 1; const int size = 1000 + 300000 ; const int INF = INT_MAX>>1; typedef long long ll; const int MAXN = 500000 + 1000; #define F(x) ((x)/3+((x)%3==1?0:tb)) #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2) int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3]; int c0(int *r,int a,int b) { return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2]; } int c12(int k,int *r,int a,int b) { if(k == 2) return r[a] < r[b] || ( r[a] == r[b] && c12(1,r,a+1,b+1) ); else return r[a] < r[b] || ( r[a] == r[b] && wv[a+1] < wv[b+1] ); } void sort(int *r,int *a,int *b,int n,int m) { int i; for(i = 0;i < n;i++)wv[i] = r[a[i]]; for(i = 0;i < m;i++)wss[i] = 0; for(i = 0;i < n;i++)wss[wv[i]]++; for(i = 1;i < m;i++)wss[i] += wss[i-1]; for(i = n-1;i >= 0;i--) b[--wss[wv[i]]] = a[i]; } void dc3(int *r,int *sa,int n,int m) { int i, j, *rn = r + n; int *san = sa + n, ta = 0, tb = (n+1)/3, tbc = 0, p; r = r[n+1] = 0; for(i = 0;i < n;i++)if(i %3 != 0)wa[tbc++] = i; sort(r + 2, wa, wb, tbc, m); sort(r + 1, wb, wa, tbc, m); sort(r, wa, wb, tbc, m); for(p = 1, rn[F(wb[0])] = 0, i = 1;i < tbc;i++) rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p - 1 : p++; if(p < tbc)dc3(rn,san,tbc,p); else for(i = 0;i < tbc;i++)san[rn[i]] = i; for(i = 0;i < tbc;i++) if(san[i] < tb)wb[ta++] = san[i] * 3; if(n % 3 == 1)wb[ta++] = n - 1; sort(r, wb, wa, ta, m); for(i = 0;i < tbc;i++)wv[wb[i] = G(san[i])] = i; for(i = 0, j = 0, p = 0;i < ta && j < tbc;p++) sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++]; for(;i < ta;p++)sa[p] = wa[i++]; for(;j < tbc;p++)sa[p] = wb[j++]; } //str和sa也要三倍 void da(int str[],int sa[],int rank[],int height[],int n,int m) { for(int i = n;i < n*3;i++) str[i] = 0; dc3(str, sa, n+1, m); int i,j,k = 0; for(i = 0;i <= n;i++)rank[sa[i]] = i; for(i = 0;i < n; i++) { if(k) k--; j = sa[rank[i]-1]; while(str[i+k] == str[j+k]) k++; height[rank[i]] = k; } } int sa[size],rrank[size],height[size]; int n,k; int str[size],len; int zone[size]; char s[size]; int vis[200]; queue<int> que; bool isok(int ll){ memset(vis,0,sizeof(vis)); while (!que.empty()) que.pop(); que.push(zone[sa[1]]); vis[zone[sa[1]]] = 1; //# for (int i=1;i<=n;i++){ //# cout << height[i] << (i==n?'\n':' '); //# } //# cout << endl; for (int i=2;i<=len;i++){ //# cout << "height " << i << " " << height[i] << endl; if (height[i]>=ll){ if (vis[zone[sa[i]]]==0){ que.push(zone[sa[i]]); vis[zone[sa[i]]] = 1; } }else { //# cout << "que.size = " << que.size() << endl; if (que.size()>n/2) return true; while (!que.empty()){ vis[que.front()] = 0; que.pop(); } que.push(zone[sa[i]]); vis[zone[sa[i]]] = 1; } } if (que.size()>n/2) return true; return false; } void Debug(int n){ for (int i=1;i<=n;i++){ cout << "*" << i << "*\t" << height[i] << "\t" << zone[sa[i]] << '\t'; PrintArray(str+sa[i],str+n,'\t'); } } int main() { int i,j; int ncase = 0; while (~scanf("%d",&n)){ if (!n) break; if (ncase++) cout << endl; len = 0; for (i=0;i<n;i++){ scanf("%s",s); for (j=0;s[j];j++){ str[len] = s[j] + 200; zone[len] = i; len++; } if (i==n-1){ str[len] = 0; } else { zone[len] = i; str[len++] = 1+i; } } //# void da(char str[],int sa[],int rrank[],int height[],int n,int m){ da(str,sa,rrank,height,len,500); int l = 0,r = len+1; while (l < r-1){ int mid = l+r>>1; if (isok(mid)){ l = mid; }else { r = mid; } } //# cout << "l = " << l << endl; //# Debug(len); if (l==0){ cout << "?" << endl; }else { memset(vis,0,sizeof(vis)); while (!que.empty()) que.pop(); que.push(zone[sa[1]]); vis[zone[sa[1]]] = 1; for (i=1;i<=len;i++){ if (height[i]>=l){ if (vis[zone[sa[i]]]==0){ que.push(zone[sa[i]]); vis[zone[sa[i]]] = 1; } }else { if (que.size()>n/2){ for (j=sa[i-1];j<sa[i-1]+l;j++){ cout << char(str[j]-200); } cout << endl; } while (!que.empty()){ vis[que.front()] = 0; que.pop(); } que.push(zone[sa[i]]); vis[zone[sa[i]]] = 1; } } if (que.size()>n/2){ for (j=sa[i-1];j<sa[i-1]+l;j++){ cout << char(str[j]-200); } cout << endl; } } } return 0; }
第二种思路
/*****************************************************************
> File Name: Cpp_Acm.cpp
> Author: Uncle_Sugar
> Mail: uncle_sugar@qq.com
> Created Time: 2016年08月01日 星期一 18时50分27秒
*****************************************************************/
# include <cstdio>
# include <cstring>
# include <cctype>
# include <cmath>
# include <cstdlib>
# include <climits>
# include <iostream>
# include <iomanip>
# include <set>
# include <map>
# include <vector>
# include <stack>
# include <queue>
# include <algorithm>
using namespace std;
# define rep(i,a,b) for (i=a;i<=b;i++)
# define rrep(i,a,b) for (i=b;i>=a;i--)
template<class T>void PrintArray(T* first,T* last,char delim=' '){
for (;first!=last;first++) cout << *first << (first+1==last?'\n':delim);
}
const int debug = 1;
const int size = 1000 + 300000 ;
const int INF = INT_MAX>>1;
typedef long long ll;
const int MAXN = 500000 + 1000;
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3];
int c0(int *r,int a,int b)
{
return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2];
}
int c12(int k,int *r,int a,int b)
{
if(k == 2)
return r[a] < r[b] || ( r[a] == r[b] && c12(1,r,a+1,b+1) );
else return r[a] < r[b] || ( r[a] == r[b] && wv[a+1] < wv[b+1] );
}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = 0;i < n;i++)wv[i] = r[a[i]];
for(i = 0;i < m;i++)wss[i] = 0;
for(i = 0;i < n;i++)wss[wv[i]]++;
for(i = 1;i < m;i++)wss[i] += wss[i-1];
for(i = n-1;i >= 0;i--)
b[--wss[wv[i]]] = a[i];
}
void dc3(int *r,int *sa,int n,int m)
{
int i, j, *rn = r + n;
int *san = sa + n, ta = 0, tb = (n+1)/3, tbc = 0, p;
r
= r[n+1] = 0;
for(i = 0;i < n;i++)if(i %3 != 0)wa[tbc++] = i;
sort(r + 2, wa, wb, tbc, m);
sort(r + 1, wb, wa, tbc, m);
sort(r, wa, wb, tbc, m);
for(p = 1, rn[F(wb[0])] = 0, i = 1;i < tbc;i++)
rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p - 1 : p++;
if(p < tbc)dc3(rn,san,tbc,p);
else for(i = 0;i < tbc;i++)san[rn[i]] = i;
for(i = 0;i < tbc;i++) if(san[i] < tb)wb[ta++] = san[i] * 3;
if(n % 3 == 1)wb[ta++] = n - 1;
sort(r, wb, wa, ta, m);
for(i = 0;i < tbc;i++)wv[wb[i] = G(san[i])] = i;
for(i = 0, j = 0, p = 0;i < ta && j < tbc;p++)
sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
for(;i < ta;p++)sa[p] = wa[i++];
for(;j < tbc;p++)sa[p] = wb[j++];
}
//str和sa也要三倍
void da(int str[],int sa[],int rank[],int height[],int n,int m)
{
for(int i = n;i < n*3;i++)
str[i] = 0;
dc3(str, sa, n+1, m);
int i,j,k = 0;
for(i = 0;i <= n;i++)rank[sa[i]] = i;
for(i = 0;i < n; i++)
{
if(k) k--;
j = sa[rank[i]-1];
while(str[i+k] == str[j+k]) k++;
height[rank[i]] = k;
}
}
int sa[size],rrank[size],height[size];
int n,k;
int str[size],len;
int zone[size];
char s[size];
int vis[200];
set<int> st;
void Debug(int n){
for (int i=1;i<=n;i++){
cout << "*" << i << "*\t" << height[i] << "\t" << zone[sa[i]] << '\t';
PrintArray(str+sa[i],str+n,'\t');
}
}
struct Comper{
int operator () (const int x,const int y){
if (height[x]==height[y])
return x<y?y:x;
return height[x] < height[y]?x:y;
}
}comp;
/*
* 这种情况下会返回最小值的下标
*/
const int MAXRMQSIZE = 110000;
struct RMQ{
int dp[MAXRMQSIZE][25];
int mm[MAXRMQSIZE];
//初始化RMQ, b数组下标从1开始,从0开始简单修改
RMQ(){}
void initRMQ(int n){
mm[0] = -1;
for(int i = 1; i <= n;i++){
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dp[i][0] = i;
}
for(int j = 1; j <= mm
;j++)
for(int i = 1;i + (1<<j) -1 <= n;i++)
dp[i][j] = comp(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
//查询最大值
int rmq(int x,int y){
if (x > y)
swap(x,y);
int k = mm[y-x+1];
return comp(dp[x][k],dp[y-(1<<k)+1][k]);
}
};
RMQ rmqq;
int ans = 0;
vector<int> anspos;
int main()
{
int i,j;
int ncase = 0;
while (~scanf("%d",&n)){
if (!n) break;
if (ncase++) cout << endl;
len = 0;
for (i=0;i<n;i++){
scanf("%s",s);
for (j=0;s[j];j++){
str[len] = s[j] + 200;
zone[len] = i;
len++;
}
if (i==n-1){
str[len] = 0;
}
else {
zone[len] = i;
str[len++] = 1+i;
}
}
//# void da(char str[],int sa[],int rrank[],int height[],int n,int m){
da(str,sa,rrank,height,len,500);
//# Debug(len);
int left,right;
st.clear();
anspos.clear();
memset(vis,0,sizeof(vis));
rmqq.initRMQ(len);
ans = 0;
for (left=right=1;left<=len;left++){
while (st.size() <= n/2 && right<=len){
if (vis[zone[sa[right]]]++==0){
st.insert(zone[sa[right]]);
}
right++;
}
if (st.size() <= n/2) break;
//# cout << "left " << left << " right " << right ;
int k = rmqq.rmq(left+1,right-1);
//# cout << "left + 1 " << left+1 << " right-1 " << right-1 << " " << height[k]<< endl;
if (height[k] > ans){
ans = height[k];
anspos.clear();
anspos.push_back(k);
}else if (height[k] == ans){
if (anspos.empty()||height[rmqq.rmq(anspos.back(),k)] < ans)
anspos.push_back(k);
}
if (--vis[zone[sa[left]]]==0){
st.erase(zone[sa[left]]);
}
}
if (ans==0){
putchar('?');
putchar('\n');
}
else{
for (i=0;i<anspos.size();i++){
int loc = sa[anspos[i]];
for (j=loc;j<loc+ans;j++){
putchar(char(str[j] - 200));
}
putchar('\n');
}
}
}
return 0;
}
相关文章推荐
- POJ-3294-Life Forms
- POJ3294--Life Forms
- 【POJ】3294 Life Forms 【后缀数组——求在超过一半串中出现的最长串】
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
- POJ 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms
- POJ 3294 Life Forms (后缀数组,求出现在不少于k个字符串的最长子串)
- [后缀数组+二分] poj 3294 Life Forms
- poj 3294 Life Forms (后缀数组)
- Poj 3294 Life Forms (后缀数组 在n个串中出现k次的最长公共子串并输出)
- 【POJ】3294 Life Forms
- poj 3294 Life Forms(不小于k 个字符串中的最长子串)
- 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 (后缀数组)
- POJ3294---Life Forms(后缀数组,二分+给后缀分组)