当前位置: 代码迷 >> 综合 >> 【POJ 3080 Blue Jeans 】 KMP/后缀数组
  详细解决方案

【POJ 3080 Blue Jeans 】 KMP/后缀数组

热度:51   发布时间:2023-12-29 02:56:34.0

POJ3080
本题题意为求m个字符串长度至少为3的最长公共子串
由于m只有10而且len小于60,我们可以选择枚举某一个串的子串并用str.find()或者kmp验证是否所有该子串在所有字符串中出现过,也可以用经典的二分长度将height数组分块的后缀数组做法
POJ3080(find解法

//由于只查找是否出现过,算法复杂度差距不大,所以这里给出简单一些的写法
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 65;
char str[maxn];
string ansstr;
string str2[maxn];
int main()
{int n,t;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=0;i<n;i++){scanf("%s",str);str2[i]=str;}int ans=0;string tmp=str2[0];int tmplen=tmp.size();for(int i=0;i<tmplen;i++){for(int j=1;i+j<=tmplen;j++){int cnt=1;string ss=tmp.substr(i,j);for(int k=1;k<n;k++){if(str2[k].find(ss)!=-1)cnt++;}if(cnt==n){if(ans<j){ans=j;ansstr=ss;}else if(ans==j){ansstr=min(ansstr,ss);}}}}if(ans<3) printf("no significant commonalities\n");else printf("%s\n",ansstr.c_str());}
}

POJ3080(后缀数组写法

//具体实现原理可以参考我的后缀数组博客
#include <iostream>
#include<algorithm>
#include <stdio.h>
#include <string.h>
using namespace std;
#define maxn 4005
const int INF = 0x3f3f3f3f;
int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];
int rank[maxn],height[maxn],s[maxn];
char str[15][65];
int t,lenn[maxn];
int belong[maxn];
int anspos;
int vis[65];
int cmp(int *r,int a,int b,int k)
{return r[a]==r[b]&&r[a+k]==r[b+k];
}
void getsa(int *r,int *sa,int n,int m)
{int i,j,p,*x=wa,*y=wb,*t;for(i=0; i<m; i++)  wsf[i]=0;for(i=0; i<=n; i++)  wsf[x[i]=r[i]]++;for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];for(i=n; i>=0; i--)  sa[--wsf[x[i]]]=i;p=1;j=1;for(; p<=n; j*=2,m=p){for(p=0,i=n+1-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++)  wsf[i]=0;for(i=0; i<=n; i++)  wsf[wv[i]]++;for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];for(i=n; i>=0; i--)  sa[--wsf[wv[i]]]=y[i];t=x;x=y;y=t;x[sa[0]]=0;for(p=1,i=1; i<=n; i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;}
}
void getheight(int *r,int n)
{int i,j,k=0;for(i=1; i<=n; i++)  rank[sa[i]]=i;for(i=0; i<n; i++){if(k)k--;elsek=0;j=sa[rank[i]-1];while(r[i+k]==r[j+k])k++;height[rank[i]]=k;}
}
int check(int x,int n)
{for(int i=1;i<=n-1;i++){if(height[i]<x) continue;int cnt=0;for(int j=0;j<=t;j++) vis[j]=0;while(height[i]>=x&&i<=n-1){if(!vis[belong[sa[i-1]]]){vis[belong[sa[i-1]]]=1;cnt++;}i++;}if(!vis[belong[sa[i-1]]]){vis[belong[sa[i-1]]]=1;cnt++;}if(cnt>=t){anspos=sa[i-1];return true;}}return false;
}
int main()
{int len,n;int casee;scanf("%d",&casee);while(casee--){scanf("%d",&t);if(t==0) break;n=0;int pos=30;for(int i=0;i<t;i++){scanf("%s",str[i]);lenn[i]=strlen(str[i]);for(int j=0;j<lenn[i];j++){s[n++]=str[i][j]-'A'+1;belong[n-1]=i;}s[n++]=pos++;}s[n]=0;getsa(s,sa,n,pos);getheight(s,n);int l=1,r=60,mid;while(l<=r){mid=(l+r)>>1;if(check(mid,n)) l=mid+1;else r=mid-1;}if(r<3) printf("no significant commonalities \n");else{for(int i=anspos;i<anspos+r;i++)printf("%c",s[i]-1+'A');printf("\n");}}return 0;
}
  相关解决方案