链接:http://poj.org/problem?id=3080
题意:给出m个字符串,找出其中最长的公共子串,如果答案有多个,输出字典序最小的子串。
分析:枚举第一个字符串的子串,然后和其他字符串进行匹配。此题也可用strstr()函数水过,而且貌似比KMP还快?
Source Code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char str[15][65],tmp[65],s[65];
int next[65],m,cas,len,ans;
void GetNext(int l){
int i=0,j=-1;
next[0]=-1;
while(i<l){
if(j==-1||tmp[i]==tmp[j]){
i++,j++;
next[i]=j;
}
else j=next[j];
}
}
bool KMP(int idx,int lent){
int i=0,j=0;
int lens=strlen(str[idx]);
while(i<lens&&j<lent){
if(j==-1||str[idx][i]==tmp[j]){
i++;j++;
}
else j=next[j];
}
if(j>=lent) return true;
return false;
}
int main()
{
scanf("%d",&cas);
while(cas--){
scanf("%d",&m);
for(int i=0;i<m;i++)
scanf("%s",str[i]);
len=strlen(str[0]);
ans=0;
bool flag=false;
for(int i=len;i>0;i--){
for(int j=0;j<=len-i;j++){
strncpy(tmp,str[0]+j,i);
tmp[i]='\0';
GetNext(i);
int k;
for(k=1;k<m;k++){
if(!KMP(k,i)) break;
}
if(k>=m){
if(i>ans){
ans=i;
flag=true;
strcpy(s,tmp);
}
else if(i==ans){
if(strcmp(s,tmp)>0) strcpy(s,tmp);
}
}
}
if(flag) break;
}
if(ans<3) printf("no significant commonalities\n");
else printf("%s\n",s);
}
return 0;
}
POJ 3450和上一题一样,但数据范围更大,可用二分优化,也可用后缀数组。但和上一题一样直接暴力也可水过。。。
Source Code:(二分:70MS+)
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=205;
char str[4005][maxn],ans[maxn],tmp[maxn];
int m,minl,maxl,idx;
int main()
{
while(scanf("%d",&m),m){
minl=1000;
for(int i=0;i<m;i++){
scanf("%s",str[i]);
if(strlen(str[i])<minl){
minl=strlen(str[i]);
idx=i;
}
}
int l=1,r=minl;
int mid;
bool flag=false;
maxl=0;
while(l<=r){
mid=(l+r)/2;
for(int i=0;i<=minl-mid;i++){
strncpy(tmp,str[idx]+i,mid);
tmp[mid]='\0';
int j;
for(j=0;j<m;j++){
if(j==idx) continue;
if(strstr(str[j],tmp)==NULL) break;
}
if(j>=m){
flag=true;
if(mid>maxl){
maxl=mid;
strcpy(ans,tmp);
}
else if(mid==maxl){
if(strcmp(tmp,ans)<0) strcpy(ans,tmp);
}
}
}
if(maxl==mid) l=mid+1;
else r=mid-1;
}
if(maxl>0) printf("%s\n",ans);
else printf("IDENTITY LOST\n");
}
return 0;
}