POJ-3294 Life Forms (后缀数组)
要按照字典序输出的话后缀自动机就比较麻烦了,所以没有
把所有字符串接在一起,中间用不同的奇怪的字符隔开
二分答案\(x\),将\(LCP\)数组分组使得每组中的\(LCP\ge x\),找一下是否一半的串都在这组中出现过了即可
输出注意格式
#include<cstdio> #include<algorithm> #include<iostream> #include<cctype> #include<cstring> #include<cassert> using namespace std; #define reg register #define pb push_back typedef long long ll; typedef unsigned long long ull; #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i) template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); } char IO; int rd(){ int s=0; int f=0; while(!isdigit(IO=getchar())) f|=(IO=='-'); do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return f?-s:s; } const int N=2e5+10,INF=1e9; int k,n,m; char str[N]; int s[N],p[N]; int cnt[N],tmp[N],rk[N<<1],sa[N],lcp[N],typ[N]; void PreMake(){ memset(cnt,0,1300); rep(i,1,n) cnt[s[i]]++; rep(i,1,300) cnt[i]+=cnt[i-1]; rep(i,1,n) rk[i]=cnt[s[i]],sa[i]=i; rep(i,n+1,n*2) rk[i]=0; for(int k=1;k<=n;k<<=1) { rep(i,0,n) cnt[i]=0; rep(i,1,n) cnt[rk[i+k]]++; rep(i,1,n) cnt[i]+=cnt[i-1]; drep(i,n,1) tmp[cnt[rk[i+k]]--]=i; ; rep(i,0,n) cnt[i]=0; rep(i,1,n) cnt[rk[i]]++; rep(i,1,n) cnt[i]+=cnt[i-1]; drep(i,n,1) sa[cnt[rk[tmp[i]]]--]=tmp[i]; ; rep(i,1,n) tmp[sa[i]]=tmp[sa[i-1]]+(rk[sa[i]]!=rk[sa[i-1]]||rk[sa[i]+k]!=rk[sa[i-1]+k]); rep(i,1,n) rk[i]=tmp[i]; } rep(i,1,n)lcp[i]=0; int h=0; rep(i,1,n) { int j=sa[rk[i]-1]; if(h) h--; while(i+h<=n && j+h<=n && s[i+h]==s[j+h]) h++; lcp[rk[i]-1]=h; } } int apr[N],apc; int Check(int lim) { rep(i,1,m) apr[i]=0;apc=0; rep(i,1,n) { int j=i; while(j<n && lcp[j]>=lim) j++; rep(k,i,j) { if(typ[sa[k]]) { apc+=!apr[typ[sa[k]]]; apr[typ[sa[k]]]=1; } } if(apc>m/2) return sa[i]; rep(k,i,j) apr[typ[sa[k]]]=0; apc=0; i=j; } return 0; } int fir=0; int main(){ while(~scanf("%d",&m) && m) { p[1]=1; rep(i,1,m) { scanf("%s",str+1); int len=strlen(str+1); rep(j,1,len) s[p[i]+j-1]=str[j]; s[p[i]+len]=i+200; p[i+1]=p[i]+len+1; } n=p[m+1]-1; rep(i,1,n) typ[i]=0; rep(i,1,m) rep(j,p[i],p[i+1]-2) typ[j]=i; PreMake(); int l=1,r=n,res=-1; while(l<=r) { int mid=(l+r)>>1; if(Check(mid)) l=mid+1,res=mid; else r=mid-1; } if(fir) puts(""); else fir=1; if(res==-1) { puts("?"); continue; } rep(i,1,m) apr[i]=0;apc=0; rep(i,1,n) { int j=i; while(j<n && lcp[j]>=res) j++; rep(k,i,j) { if(typ[sa[k]]) { apc+=!apr[typ[sa[k]]]; apr[typ[sa[k]]]=1; } } if(apc>m/2) { rep(k,sa[i],sa[i]+res-1) putchar(s[k]); puts(""); } rep(k,i,j) apr[typ[sa[k]]]=0; apc=0; i=j; } } }
来源:https://www.cnblogs.com/chasedeath/p/12213662.html