poj 1226 Substrings

来源:互联网 发布:档案管理源码 编辑:程序博客网 时间:2024/06/07 19:45

求多个字符串的最长公共字串

利用后缀数组求解,将所有的字符串连接成一个长的字符串,二分所有字符串中最短的字符串的长度mid为公共前缀的长度,求出所有满足公共前缀长度大于等于mid的后缀,判断所有的字符串是否都包含在这些后缀中,都包含,则mid为一个可行的长度。


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 200005int wa[maxn],wb[maxn],wv[maxn],Ws[maxn];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++;}}int sa[maxn],Rank[maxn],height[maxn];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++);}int str[maxn];int local[maxn];bool flag[105];int solve(int minlen,int n,int cnt){int s = 0,e = minlen,mid,appear,ans = 0;while(s<=e){memset(flag,0,sizeof(flag));appear = 0;mid = (s+e)>>1;bool tmp = false;for(int i = 1;i<=n;i++){if(height[i]>=mid){int num = local[sa[i]];if(!flag[num]){appear++;flag[num] = 1;}if(appear==cnt){tmp = true;break;}}else{appear = 0;memset(flag,0,sizeof(flag));int num = local[sa[i]];appear++;flag[num] = 1;}}if(tmp){s = mid+1;ans = mid;}else{e = mid-1;}}return ans;}int main(){int t,n,minlen=105;int spe = 500;char s[200];for(scanf("%d",&t);t;t--){scanf("%d",&n);minlen = 105;int k = 0;for(int i = 0;i<n;i++){scanf("%s",s);int len = strlen(s);if(len < minlen)minlen = len;for(int j = 0;j<len;j++){str[k] = s[j];local[k++] = i;}str[k] = spe++;local[k++] = i;for(int j = len-1;j>=0;j--){str[k] = s[j];local[k++] = i;}str[k] = spe++;local[k++] = i;}str[k] = 0;local[k] = n;da(str,sa,k+1,spe);calheight(str,sa,k);int ans = solve(minlen,k,n);printf("%d\n",ans);}}


原创粉丝点击