poj 3294 后缀数组
2012-04-20 14:28
288 查看
【题意】
给定N个串,求最长的子串S,使得S为其中超过一半的串的公共子串。
【题解】
后缀数组,按height数组分组,按sa数组输出。
【代码】
给定N个串,求最长的子串S,使得S为其中超过一半的串的公共子串。
【题解】
后缀数组,按height数组分组,按sa数组输出。
【代码】
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int maxn=200000; int s[maxn],w[maxn],wa[maxn],wb[maxn],x[maxn],y[maxn],sa[maxn],rk[maxn]; int v[maxn],tp[maxn],h[maxn]; char st[1500]; int nn,n,m,ans; int cmp(int* r,int a,int b,int l) { return r[a]==r[b] && r[a+l]==r[b+l]; } void da(int* s,int* sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for (i=0;i<m;i++) w[i]=0; for (i=0;i<n;i++) w[x[i]=s[i]]++; for (i=1;i<m;i++) w[i]+=w[i-1]; for (i=n-1;i>=0;i--) sa[--w[x[i]]]=i; for (j=1,p=1;p<n;m=p,j*=2) { 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++) w[i]=0; for (i=0;i<n;i++) v[i]=x[y[i]]; for (i=0;i<n;i++) w[v[i]]++; for (i=1;i<m;i++) w[i]+=w[i-1]; for (i=n-1;i>=0;i--) sa[--w[v[i]]]=y[i]; for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } void calheight() { int i,j,k=0; for (i=1;i<=n;i++) rk[sa[i]]=i; for (i=0;i<n;h[rk[i++]]=k) for (k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++); } bool ok(int mid) { bool v[105]={0}; int tot=0,i; for (i=1;i<=n;i++) { if (h[i]<mid) { memset(v,0,sizeof(v)); v[tp[sa[i]]]=true; tot=1; } else if (!v[tp[sa[i]]]) { v[tp[sa[i]]]=true; tot++; } if (tot>nn/2) return true; } return false; } int work() { int ll=1,rr=1000,mid,ans=0; while (ll<=rr) { mid=(ll+rr)/2; if (ok(mid)) ans=mid,ll=mid+1; else rr=mid-1; } return ans; } void print(int ans) { int tot=0,i,j; bool v[105]={0}; for (i=1;i<=n;i++) { if (h[i]<ans) { if (tot>nn/2) { for (j=0;j<ans;j++) printf("%c",s[sa[i-1]+j]); printf("\n"); } memset(v,0,sizeof(v)); v[tp[sa[i]]]=true; tot=1; } else if (!v[tp[sa[i]]]) { v[tp[sa[i]]]=true; tot++; } } } int main() { freopen("pin.txt","r",stdin); freopen("pou.txt","w",stdout); int i,j,t=0; while (1) { scanf("%d",&nn); if (nn==0) break; if (t) printf("\n"); t=1; n=0; for (i=1;i<=nn;i++) { scanf("%s",st); for (j=0;j<strlen(st);j++) { s =st[j]; tp[n++]=i; } if (i==nn) break; s =i+200;tp[n++]=0; } s =0; da(s,sa,n+1,400); calheight(); ans=work(); if (ans==0) printf("?\n"); else print(ans); } return 0; }
相关文章推荐
- poj 3294(后缀数组)
- 后缀数组(多个字符串的最长公共子串)—— POJ 3294
- poj 3294 Life Forms (后缀数组)
- poj 3294 Life Forms (后缀数组应用)
- poj 3294(Life Forms) 2分+ 后缀数组
- POJ 3294 Life Forms(后缀数组)
- poj 3294 Life Forms 后缀数组
- poj3294 Life Forms(后缀数组)
- POJ-3294 Life Forms 后缀数组
- POJ 3294 Life Forms (后缀数组)
- POJ 3294 Life Forms(后缀数组)
- POJ3294——Life Forms 后缀数组
- POJ 3294 (UVA 11107) Life Forms 后缀数组
- poj 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms (后缀数组)
- POJ 3294 Life Forms 后缀数组
- poj 3294 Life Forms (后缀数组)
- poj 3294 后缀数组
- POJ 3294 Life Forms(后缀数组)
- poj 3294 Life Forms 求n(n>1)个字符串的最长的一个子串 后缀数组