spoj220 每个字符串至少出现两次且不重叠的最长子串(后缀数组)

来源:互联网 发布:java下载文件代码 编辑:程序博客网 时间:2024/05/17 02:33
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <string.h>#include <queue>                    //spoj220  每个字符串至少出现两次且不重叠的最长子串(后缀数组)using namespace std;#define maxn 200010using namespace std;int wa[maxn],wb[maxn],wv[maxn],Ws[maxn], Rank[maxn], height[maxn], sa[maxn];char p[10010];int max1, min1, a[maxn], num[maxn], vis[15], vis1[15];struct tag1{int l, r;}tag[15];     //用来标记每个字符串的前后,从而判断是否重叠void init(tag1 *q){for(int t=0; t<15; ++t){q[t].l=1<<30;q[t].r=0;}return ;}int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}void da(const int *r,int *sa,int n,int m)      {int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) Ws[i]=0; for(i=0;i<n;i++) Ws[x[i]=r[i]]++; for(i=1;i<m;i++) Ws[i]+=Ws[i-1]; for(i=n-1;i>=0;i--) sa[--Ws[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p){ 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<n;i++) wv[i]=x[y[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--) sa[--Ws[wv[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++; } return; }void calheight(const int *r,int *sa,int n){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++);return;}bool check(int k, int n, int j){int t, h;init(tag);for(t=1; t<=j; ++t){if(height[t]>=k)      {if(sa[t-1]>tag[num[sa[t-1]]].r)tag[num[sa[t-1]]].r=sa[t-1];if(sa[t-1]<tag[num[sa[t-1]]].l)tag[num[sa[t-1]]].l=sa[t-1];if(sa[t]>tag[num[sa[t]]].r)tag[num[sa[t]]].r=sa[t];if(sa[t]<tag[num[sa[t]]].l)tag[num[sa[t]]].l=sa[t];for(h=0; h<n; ++h){if(tag[h].r-tag[h].l<k)break;}if(h==n)return true;}else {init(tag);tag[num[sa[t]]].l=tag[num[sa[t]]].r=sa[t];}}return false;}int main(){int n, i, t, j, k, min, ans, T;scanf("%d", &T);while(T--){scanf("%d", &n);min=-1;ans=0;for(i=k=0; i<n; ++i){scanf("%s", p);j=strlen(p);if(j>min)min=j;for(t=0; t<j; ++t){a[k]=p[t]-'a'+1;   num[k++]=i; }a[k]=i+30;num[k++]=i+100;}a[k]=0;   da(a, sa, k+1, 200);calheight(a, sa, k);int l=0, r=min, mid;while(l<=r)  {mid=(l+r)>>1;if(check(mid, n, k)){l=mid+1;ans=mid;}else r=mid-1;}printf("%d\n", ans);}return 0;}

原创粉丝点击