您的位置:首页 > Web前端

poj 3294 Life Forms 后缀数组

2012-02-09 13:39 344 查看
题意:给n个字符串,求一个最长的子串至少出现在[n/2+1]个字符串中

思路:后缀数组 把所有字串连一起,并用不同的字符隔开 二分

P.S. 1. 我的程序C++WA,G++ AC

   2. 为什么char的上界是127啊

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 110000
int n,m;
int suffix_array[MAXN];
int rank[2*MAXN],oldrank[2*MAXN];
int cnt[MAXN],tmp[MAXN];
int height[MAXN];
int a[MAXN];
int mark[MAXN];
void SuffixArray()
{
int memo[300];
suffix_array[0]=0;
memset(memo,0,sizeof(memo));
memset(rank,0,sizeof(rank));
memset(oldrank,0,sizeof(oldrank));
int i,l;
for(i=1;i<=n;i++) memo[a[i]]=1;
for(i=1;i<300;i++) memo[i]+=memo[i-1];
for(i=1;i<=n;i++) rank[i]=memo[a[i]];
for(l=1;l<=n;l*=2)
{
memset(cnt,0,sizeof(cnt));
for(i=1;i<=n;i++) cnt[rank[i+l]]++;
for(i=1;i<=n;i++) cnt[i]+=cnt[i-1];
for(i=1;i<=n;i++) tmp[cnt[rank[i+l]]--]=i;

memset(cnt,0,sizeof(cnt));
for(i=1;i<=n;i++) cnt[rank[tmp[i]]]++;
for(i=1;i<=n;i++) cnt[i]+=cnt[i-1];
for(i=n;i>0;i--) suffix_array[cnt[rank[tmp[i]]]--]=tmp[i];

memcpy(oldrank,rank,sizeof(rank));
rank[suffix_array[1]]=1;
int k=1;
for(i=2;i<=n;i++)
{
int x=suffix_array[i-1],y=suffix_array[i];
if(oldrank[x]!=oldrank[y]||oldrank[x+l]!=oldrank[y+l]) k++;
rank[y]=k;
}
if(k==n) break;
}
}
void LCP()
{
int i,j,k=0;
for(i=1;i<=n;i++)
{
if(rank[i]==n)
{
height
=k=0; continue;
}
j=suffix_array[rank[i]+1];
k=max(k-1,0);
while(a[j+k]==a[i+k]) k++;
height[rank[i]]=k;
}
height[0]=-1; mark[0]=m+1;
}
bool check(int mid,bool w)
{
bool use[102];
memset(use,0,sizeof(use));
int k=1;
int i,j;
for(i=1;i<=n;i++)
{
if(a[suffix_array[i-1]]>'z') break;
if(height[i-1]>=mid)
{
if(use[mark[suffix_array[i]]]==0)
{
use[mark[suffix_array[i]]]=1;
k++;
}
}
else
{
if(k>m/2)
{
if(w==0) return 1;
for(j=suffix_array[i-1];j<=suffix_array[i-1]+mid-1;j++)
printf("%c",a[j]);
printf("\n");
}
memset(use,0,sizeof(use));
k=1; use[mark[suffix_array[i]]]=1;
}

}
if(w==0)
return 0;
printf("\n");
}
int binary()
{
int left=0,right=n+1;
int mid;
while(left<right)
{
mid=(left+right)/2;
if(check(mid,0)) left=mid;
else right=mid;
if(right-left==1) return left;
}
}
int main()
{
char c[1001];
scanf("%d",&m);
int i,j,l,k;
int maxl;
while(m!=0)
{
memset(a,0,sizeof(a));
j=1;
for(i=1;i<=m;i++)
{
scanf("%s",c);
l=strlen(c);
for(k=j;k<=l+j-1;k++)
{
mark[k]=i;
a[k]=c[k-j];
}
j=j+l; mark[j]=m+1; a[j]='z'+i;
j++;
}
if(m==1)
{
printf("%s\n\n",c);
scanf("%d",&m);
continue;
}
n=j-2;
SuffixArray();
LCP();
maxl=binary();
if(maxl!=0) check(maxl,1);
else printf("?\n\n");
scanf("%d",&m);
}
return 0;
}


答案
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: