spoj 220 Relevant Phrases of Annihilation(n个串的最长公共重复2次子串)

来源:互联网 发布:手机打印软件免费版 编辑:程序博客网 时间:2024/05/16 18:14

地址:http://www.spoj.com/problems/PHRASES/

题意:给你n个串,求最长的公共重复子串

分析:跟两个串的最长的公共重复子串差不多,也是将所有串合成一个串,构造后缀数组,然后二分子串长度,在满足条件的区间里,求出n的串的下标的上下界的差值大于等于当前长度,所有串都满足说明存在解,否则无解。。。

代码:

/** 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<char, N> msa;char s[N],tmp[N];int p[N],low[22],high[22];int n;bool ok(int m){    int i=0,j,k;    while(i<msa.len)    {        while(i<msa.len&&msa.height[i]<m)++i;        j=i-1;        UPTO(k,1,n)low[k]=msa.len,high[k]=-1;        do        {            k=msa.sa[j++];            low[p[k]]=min(low[p[k]],k);            high[p[k]]=max(high[p[k]],k);        }while(j<msa.len&&msa.height[j]>=m);        UPTO(k,1,n)            if(high[k]-low[k]<m)break;        if(k>n)return 1;        i=j;    }    return 0;}int main(){    int i,j,k,m,t,ans;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        m=0;        UPTO(i,1,n)        {            scanf("%s",tmp);            k=strlen(tmp);            REP(j,k)                s[m+j]=tmp[j],p[m+j]=i;            p[m+k]=0;            s[m+k]=i;            m=m+k+1;        }        m--;        msa.initSA(s,m,256);        ans=i=0,j=m;        while(i<=j)        {            m=(i+j)>>1;            if(ok(m))ans=m,i=m+1;            else j=m-1;        }        printf("%d\n",ans);    }return 0;}