Poj 3294 Life Forms (后缀数组 在n个串中出现k次的最长公共子串并输出)
2013-08-07 10:06
429 查看
题意:给出n个字符串,求一个最长的子串,它至少出现在n/2+1个字符串中,如果存在,按字典序输出,若不存在,输出?。
思路:和上一题思路一样,具体可参见上篇和上上篇博文。本题多了一个输出。注意分隔符需要变化且不在原串中出现,否则出bug。数组要考虑到分隔符的数量,需要开大些。测试数据里貌似没有n==1的情况,我这个程序貌似n==1时跑不出正确结果
分隔符不变化:
![](http://img.blog.csdn.net/20130807100535437?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2h5b3J3aG50/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2014-6-24 更新
用DC3重写了代码,修正了原代码中的一些小问题。Poj 可以跑到 266ms
思路:和上一题思路一样,具体可参见上篇和上上篇博文。本题多了一个输出。注意分隔符需要变化且不在原串中出现,否则出bug。数组要考虑到分隔符的数量,需要开大些。测试数据里貌似没有n==1的情况,我这个程序貌似n==1时跑不出正确结果
分隔符不变化:
2014-6-24 更新
用DC3重写了代码,修正了原代码中的一些小问题。Poj 可以跑到 266ms
#include <cstdio> #include <cstring> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int N = int(1e5)+200; //所有串总长 多个分隔符 #define F(x) ((x)/3+((x)%3==1?0:tb)) #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2) int wa ,wb ,wv ,ws ; 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++) 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--) b[--ws[wv[i]]]=a[i]; } void DC3 (int *r,int *sa,int n,int m){ int i,j,*rn=r+n,*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++]; } int rank ,height ,sa[3*N],data[3*N]; void calheight(int *r,int *sa,int n){ // memset(height,0,sizeof(height)); // memset(rank,0,sizeof(rank)); int i,j,k=0; for(i=1;i<=n;i++) rank[sa[i]]=i; for(i=0;i<n; height[rank[i++]] = k ) for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++); } int loc ,ans ; int n,q,num; char str[1005]; bool vis[1005]; bool Judge (int x) { int i,j; bool flag=false; for (i=1;i<=n;i++) { int cnt=0; int L=i; while (L<=n && height[L]<x) L++; if (L>n) break; int R=L; while (R<=n && height[R]>=x) R++; if (R-L+2<q/2) {//R-L+1个height数组元素对应R-L+2个SA i=R; continue; } memset(vis,false,sizeof(vis)); for (j=L-1;j<=R-1;j++) if (loc[sa[j]]!=-1) vis[loc[sa[j]]]=true; for (j=1;j<=q;j++) if (vis[j]) cnt++; if (cnt>q/2) //在超过半数的字符串中出现 if (flag) ans[++num]=sa[L-1]; else { ans[num=1]=sa[L-1]; flag=true; } i=R; } return flag; } void Input () { int i,sign=130;//分隔符 n=0; for (int id=1;id<=q;id++) { scanf("%s",str); int len=strlen(str); for (i=0;i<len;i++) { loc =id; data[n++]=(int)str[i]; } loc =-1; data[n++]=sign++; //注意分隔符需变化 } data =0; DC3(data,sa,n+1,sign+5); calheight(data,sa,n); } int main () { bool flag=false; //用于输出空行 while (scanf("%d",&q),q) { Input (); if (flag) printf("\n"); flag=true; int low=0,high=n,mid,res=0; while (low<high) { mid = (low+high)>>1; if (Judge(mid)) res=mid,low=mid+1; else high=mid; } if (res == 0) printf("?\n"); else { for (int i=1;i<=num;i++) { int k=ans[i]; // 开始位置 for (int j=0;j<res;j++) //res子串长度 printf("%c",(char)data[k+j]); printf("\n"); } } } return 0; }
相关文章推荐
- POJ 3294 Life Forms (后缀数组,求出现在不少于k个字符串的最长子串)
- POJ 题目3294Life Forms(后缀数组求超过k个的串的最长公共子串)
- POJ 3294 Life Forms (后缀数组,求出现在不少于k个字符串的最长子串)
- 【POJ】3294 Life Forms 【后缀数组——求在超过一半串中出现的最长串】
- poj 3294 后缀数组求至少在k个串中出现的公共子串
- POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)
- poj 3294 求多于k个字符串的最长公共子串的个数-------后缀数组+二分答案
- poj 3294 Life Forms(n个字符串中 求公共子串长度超过k得最大子串 后缀数组)
- POJ 3294 Life Forms(不小于k个字符串中的最长子串 后缀数组)
- POJ 3294 Life Forms(后缀数组求k个串的最长子串)
- poj 2774 最长公共子串 后缀数组
- POJ 2774 后缀数组:求最长公共子串
- poj 3450 Corporate Identity【后缀数组,求多个串的最长公共子串】
- poj 2774 最长公共子串 后缀数组
- POJ 2774 Long Long Message 后缀数组求最长公共子串
- hdu1403 && poj 2774 最长公共子串 后缀数组
- POJ2774 Long Long Message (后缀数组—最长公共子串)
- POJ 2774 Long Long Message(后缀数组求最长公共子串,4级)
- POJ-2774-Long Long Message(后缀数组-最长公共子串)
- POJ 2774 Long Long Message(后缀数组求最长公共子串,4级)