题目大意:
求在m个串中同时出现两次以上且不覆盖的子串的长度。
思路分析:
二分答案,然后check是否满足,判断不覆盖的方法就是用up down 来处理边界。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <map> #include <string> #define maxn 110005 using namespace std; char str[maxn]; int sa[maxn],t1[maxn],t2[maxn],c[maxn],n; void suffix(int m) { int *x=t1,*y=t2; for(int i=0; i<m; i++)c[i]=0; for(int i=0; i<n; i++)c[x[i]=str[i]]++; for(int i=1; i<m; i++)c[i]+=c[i-1]; for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i; for(int k=1; k<=n; k<<=1) { int p=0; for(int i=n-k; i<n; i++)y[p++]=i; for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k; for(int i=0; i<m; i++)c[i]=0; for(int i=0; i<n; i++)c[x[y[i]]]++; for(int i=0; i<m; i++)c[i]+=c[i-1]; for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(int i=1; i<n; i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n)break; m=p; } } int rank[maxn],height[maxn]; void getheight() { int k=0; for(int i=0; i<n; i++)rank[sa[i]]=i; for(int i=0; i<n; i++) { if(k)k--; if(!rank[i])continue; int j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; } } int dex[maxn]; int cnt[11]; char tmp[maxn]; int len[maxn]; int up[11]; int down[11]; bool ok(int len,int m) { for(int i=1;i<=m;i++) if(up[i]-down[i]<len)return false; return true; } bool check(int len,int m) { memset(up,-1,sizeof up); memset(down,-1,sizeof down); for(int i=1;i<n;i++) { if(height[i]<len) { if(ok(len,m))return true; memset(up,-1,sizeof up); memset(down,-1,sizeof down); int index=dex[sa[i]]; up[index]=down[index]=sa[i]; } else { int index=dex[sa[i]]; if(up[index]!=-1){ up[index]=max(up[index],sa[i]); down[index]=min(down[index],sa[i]); } else up[index]=down[index]=sa[i]; } } return false; } int main() { int T; scanf("%d",&T); while(T--) { n=0; int m; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",tmp); len[i]=strlen(tmp); for(int j=n;j<len[i]+n;j++) { str[j]=tmp[j-n]; dex[j]=i; } n+=len[i]+1; str[n-1]=i+'A'; dex[n-1]=i; } str[n-1]=0; suffix(256); getheight(); int l=1,r=10000,ans=0; while(l<=r) { int mid=(l+r)>>1; if(check(mid,m)) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); } return 0; }
SPOJ 220 Relevant Phrases of Annihilation (后缀数组),布布扣,bubuko.com
SPOJ 220 Relevant Phrases of Annihilation (后缀数组)
原文地址:http://blog.csdn.net/u010709592/article/details/36457419