链接: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; }