poj 3294 Life Forms (后缀数组应用)
2015-03-07 10:43
393 查看
题意:
给出n个串,求这个n个串中至少是n/2个串的最长公共子串,注意要>n/2.
题解:
后缀数组的应用之一,做法:
1、将n个字符串拼接在一起,每个字符串拼接的符号最好是小于所有串的,这样排序以后会跑到开头,比较好处理,其实可以将字符串装化为int,同时加上10,这样会省去很多麻烦。
2、跑一边后缀数组,,二分答案,判定答案:根据height进行分组(这种方法经常有),每组的公共前缀至少都要>n/2.最后通过最终长度在进行分组一次去的答案。我是用set保存string类都用上了,虽然处理方便但是处理时间很慢1900多ms。
注意一点,要将每个位置是哪个字符串上的对应起来,我们用一个数组保存。
给出n个串,求这个n个串中至少是n/2个串的最长公共子串,注意要>n/2.
题解:
后缀数组的应用之一,做法:
1、将n个字符串拼接在一起,每个字符串拼接的符号最好是小于所有串的,这样排序以后会跑到开头,比较好处理,其实可以将字符串装化为int,同时加上10,这样会省去很多麻烦。
2、跑一边后缀数组,,二分答案,判定答案:根据height进行分组(这种方法经常有),每组的公共前缀至少都要>n/2.最后通过最终长度在进行分组一次去的答案。我是用set保存string类都用上了,虽然处理方便但是处理时间很慢1900多ms。
注意一点,要将每个位置是哪个字符串上的对应起来,我们用一个数组保存。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define B(x) (1<<(x)) typedef long long ll; const int oo=0x3f3f3f3f; const ll OO=1LL<<61; const int MOD=10007; const int maxn=111111; int rank[maxn],SA[maxn],height[maxn]; int t1[maxn],t2[maxn],t3[maxn],t4[maxn]; char str[maxn]; int ss[maxn],which[maxn],res[maxn],k,n; int len[maxn]; set<int>g; set<string>set_string; void Swap(int*& x,int*& y){ int *temp=x; x=y; y=temp; } int cmp(int t[],int a,int b,int l){ return t[a]==t[b]&&t[a+l]==t[b+l]; } void build_SA(int s[],int len,int up){ int *k1=t1,*k2=t2,*r=t3,*cnt=t4; for(int i=0;i<up;i++)cnt[i]=0; for(int i=0;i<len;i++)cnt[k1[i]=s[i]]++; for(int i=1;i<up;i++)cnt[i]+=cnt[i-1]; for(int i=len-1;i>=0;i--)SA[--cnt[k1[i]]]=i; for(int d=1,p=1;p<len;d<<=1,up=p){ p=0; for(int i=len-d;i<len;i++)k2[p++]=i; for(int i=0;i<len;i++)if(SA[i]>=d)k2[p++]=SA[i]-d; for(int i=0;i<len;i++)r[i]=k1[k2[i]]; for(int i=0;i<up;i++)cnt[i]=0; for(int i=0;i<len;i++)cnt[r[i]]++; for(int i=1;i<up;i++)cnt[i]+=cnt[i-1]; for(int i=len-1;i>=0;i--)SA[--cnt[r[i]]]=k2[i]; Swap(k1,k2); k1[SA[0]]=0; p=1; for(int i=1;i<len;i++){ k1[SA[i]]= cmp(k2,SA[i-1],SA[i],d) ? p-1 : p++; } } } void get_height(int s[],int len){ for(int i=1;i<=len;i++)rank[SA[i]]=i; for(int i=0,p=0;i<len;i++){ int j=SA[rank[i]-1]; while(s[i+p]==s[j+p])p++; height[rank[i]]=p; if(p)p--; } } bool ok(int tag,int len){ int i=n; while(1){ while(i<=len&&height[i]<tag)i++; if(i>len)break; g.clear(); g.insert(which[SA[i-1]]); while(i<=len&&height[i]>=tag){ g.insert(which[SA[i]]); i++; } if(g.size()>k)return true; } return false; } int solve(int len){ g.clear(); int l=0,r=len,mid,ans=0; while(l<=r){ mid=(r+l)>>1; if(ok(mid,len)){ ans=mid; l=mid+1; }else{ r=mid-1; } } return ans; } void Debug(int start,int L){ for(int i=start;i<=start+L-1;i++){ printf("%c",(char)(ss[i]-100)); } puts(""); } void output(int tag,int len){ int i=n; int L=tag; int tol=0; set_string.clear(); string x; while(1){ while(i<=len&&height[i]<tag)i++; if(i>len)break; g.clear(); g.insert(which[SA[i-1]]); tol=0; res[tol++]=SA[i-1]; while(i<=len&&height[i]>=tag){ res[tol++]=SA[i]; g.insert(which[SA[i]]); i++; } if(g.size()>k){ for(int t=0;t<tol;t++){ x=""; for(int i=res[t];i<=res[t]+L-1;i++) x+=(char)(ss[i]-100); set_string.insert(x); } } } for(set<string>::iterator it=set_string.begin();it!=set_string.end();++it) cout<<*it<<endl; } int main(){ int l,f=0; while(scanf("%d",&n)!=EOF){ if(n==0)break; if(f) puts(""); else f=1; k=n/2; l=0; for(int i=1;i<=n;i++){ scanf("%s",str); len[i]=strlen(str); for(int j=0;j<len[i];j++){ which[l]=i; ss[l++]=str[j]+100; } which[l]=0; ss[l++]=i; } l--; build_SA(ss,l+1,300); get_height(ss,l); int ans=solve(l); if(ans!=0) output(ans,l); else printf("?\n"); } return 0; } /** 2 adsf asdf 2 fdsa df 5 abcd bcde cdef defg efgh 5 nshiyedashai goanshab woshidiyi firstorloser iamthefirst 4 acaaaaaaaaaaaaa aaaaa aa a 4 aa a d d 2 pabcp pertp 0 */
相关文章推荐
- poj 3294(Life Forms) 2分+ 后缀数组
- poj 3294 Life Forms (后缀数组)
- POJ 3294 Life Forms (后缀数组)
- poj3294 Life Forms(后缀数组)
- POJ 3294 Life Forms(后缀数组)
- POJ3294——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 求n(n>1)个字符串的最长的一个子串 后缀数组
- poj3294 二分+后缀数组
- poj 3294 Life Forms
- POJ-3294-Life Forms