题目:http://poj.org/problem?id=3294
题意:给你n给字符串,求在一半以上的串里重复出现的最长子串
分析:将所有字符串合成一个串,字符串自己用不同的字符标记间隔,然后构造新字符串的后缀数组,很容易发现,相同子串一定在后缀数组里相邻,只要判断一个区间里的子串里是否包括了超过一半的不同串,我们只要二分子串的长度,就能得到一些区间,height数组大小都大于等于该长度,这些区间如果有超过一半的不同串,说明有解,就保存当前的解即可。。。
好吧,这个思路不是我想的,我的思路是找到所有包括不同串个数大于一半的区间,然后这个区间的最长公共前缀是否超过答案
代码:
/** head files*/ #include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <stack> #include <fstream> #include <numeric> #include <iomanip> #include <bitset> #include <list> #include <stdexcept> #include <functional> #include <utility> #include <ctime> using namespace std; /** some operate*/ #define PB push_back #define MP make_pair #define REP(i,n) for(i=0;i<(n);++i) #define UPTO(i,l,h) for(i=(l);i<=(h);++i) #define DOWN(i,h,l) for(i=(h);i>=(l);--i) #define MSET(arr,val) memset(arr,val,sizeof(arr)) #define MAX3(a,b,c) max(a,max(b,c)) #define MAX4(a,b,c,d) max(max(a,b),max(c,d)) #define MIN3(a,b,c) min(a,min(b,c)) #define MIN4(a,b,c,d) min(min(a,b),min(c,d)) /** some const*/ #define N 222222 #define M 222222 #define PI acos(-1.0) #define oo 1111111111 /** some alias*/ typedef long long ll; /** Global variables*/ /** some template names, just push ctrl+j to get it in*/ //manacher 求最长回文子串 //pqueue 优先队列 //combk n元素序列的第m小的组合和 //pmatrix n个点的最大子矩阵 //suffixarray 后缀数组 template <typename T, int LEN> struct suffixarray { int str[LEN*3],sa[LEN*3]; int rank[LEN],height[LEN]; int id[LEN]; int len; bool equal(int *str, int a, int b) { return str[a]==str[b]&&str[a+1]==str[b+1]&&str[a+2]==str[b+2]; } bool cmp3(int *str, int *nstr, int a, int b) { if(str[a]!=str[b])return str[a]<str[b]; if(str[a+1]!=str[b+1])return str[a+1]<str[b+1]; return nstr[a+b%3]<nstr[b+b%3]; } void radixsort(int *str, int *sa, int *res, int n, int m) { int i; REP(i,m)id[i]=0; REP(i,n)++id[str[sa[i]]]; REP(i,m)id[i+1]+=id[i]; DOWN(i,n-1,0)res[--id[str[sa[i]]]]=sa[i]; } void dc3(int *str, int *sa, int n, int m) { #define F(x) ((x)/3+((x)%3==1?0:one)) #define G(x) ((x)<one?(x)*3+1:((x)-one)*3+2) int *nstr=str+n, *nsa=sa+n, *tmpa=rank, *tmpb=height; int i,j,k,len=0,num=0,zero=0,one=(n+1)/3; REP(i,n)if(i%3)tmpa[len++]=i; str[n]=str[n+1]=0; radixsort(str+2, tmpa, tmpb, len, m); radixsort(str+1, tmpb, tmpa, len, m); radixsort(str+0, tmpa, tmpb, len, m); nstr[F(tmpb[0])]=num++; UPTO(i,1,len-1) nstr[F(tmpb[i])]=equal(str,tmpb[i-1],tmpb[i])?num-1:num++; if(num<len)dc3(nstr,nsa,len,num); else REP(i,len)nsa[nstr[i]]=i; if(n%3==1)tmpa[zero++]=n-1; REP(i,len)if(nsa[i]<one)tmpa[zero++]=nsa[i]*3; radixsort(str, tmpa, tmpb, zero, m); REP(i,len)tmpa[nsa[i]=G(nsa[i])]=i; i=j=0; REP(k,n) if(j>=len||(i<zero&&cmp3(str,tmpa,tmpb[i],nsa[j])))sa[k]=tmpb[i++]; else sa[k]=nsa[j++]; } void initSA(T *s, int n,int m) { int i,j,k=0; str[len=n]=0; REP(i,n)str[i]=s[i]; dc3(str,sa,n+1,m); REP(i,n)sa[i]=sa[i+1]; REP(i,n)rank[sa[i]]=i; REP(i,n) { if(k)--k; if(rank[i])for(j=sa[rank[i]-1];str[i+k]==str[j+k];++k); else k=0; height[rank[i]]=k; } } }; suffixarray<int , N> msa; int s[N]; char tmp[1111]; int out[1111]; int dd[N],vis[111]; int r,ans; bool ok(int mid, int lit) { int i=0,j,num,flag=1; while(i<msa.len) { while(i<msa.len&&msa.height[i]<mid)++i; j=i-1; MSET(vis,0); num=0; if(!vis[dd[msa.sa[j++]]]++)++num; while(j<msa.len&&msa.height[j]>=mid) if(!vis[dd[msa.sa[j++]]]++)++num; if(num>lit) { ans=mid; if(flag)r=flag=0; out[r++]=msa.sa[i]; } i=j; } return !flag; } int main() { int i,j,k,n,m,cs=0; while(scanf("%d",&n),n!=0) { if(cs++)puts(""); m=0; UPTO(i,1,n) { scanf("%s",tmp); k=strlen(tmp); REP(j,k) { s[m+j]=tmp[j]+111; dd[m+j]=i; } dd[m+k]=0; s[m+k]=i; m=m+k+(i<n); } if(n<2) { puts(tmp); continue; } msa.initSA(s,m,356); ans=i=0,j=1111; while(i<=j) { m=(i+j)>>1; if(ok(m,n/2))i=m+1; else j=m-1; } if(ans) { REP(i,r) { REP(j,ans)printf("%c",s[out[i]+j]-111); puts(""); } } else puts("?"); } return 0; }