POJ 3450 Corporate Identity 、 POJ 3080 Blue Jeans

来源:互联网 发布:js 人际关系图插件 编辑:程序博客网 时间:2024/06/05 18:59

这两题都是找出所给字符串的最长公共子串。

本来是简单的枚举,直接枚举第一个串s[0]的所有子串(从长到短),看是否是其他所有字符串的子串,若是,则只需再将s[0]的相同长度的其他子串检测一遍就好了。

再找满足条件的子串中的最小串就很简单了(其实检测过程中比较一下即可)。但该方法效率太低,超时。

怎样才能高效呢?

具体是这样的:

枚举s[0]的所有后缀,以后缀为匹配串,将其与其他串匹配。在匹配过程中,即调用KMP()函数时,可以根据 匹配过程中的J 的值来确定其他串与该后缀的最大匹配,以此来确定该后缀能与其他字符串的最大匹配的前缀,(有点晕的话看代码吧,可能容易理解点)然后取出前缀。由此即可找到所求最长公共子串。

POJ 3450 Corporate Identity

代码:

#include <stdio.h>#include <iostream>#include <string>#include <algorithm>using namespace std;int h,n,m,p[101],MAX;string b,s[4000];void getp(){p[0]=-1;int j=-1;for(int i=1;i<m;i++){while(j>-1&&b[j+1]!=b[i]) j=p[j];if(b[j+1]==b[i]) j+=1;p[i]=j;}}void kmp(){m=b.size();MAX=200;getp();for(int k=1;k<h;k++){int ma=0;int i,j;j=-1;n=s[k].size();for(i=0;i<n;i++){while(j>-1&&b[j+1]!=s[k][i]) j=p[j];if(b[j+1]==s[k][i]) j+=1;if(j==m-1){ma=m;break;//j=p[j];}if((j+1)>ma)ma=j+1;}if(ma<MAX)MAX=ma;}}int main(){string re1,re2;int _size;while(cin>>h&&h){_size=0;for(int i=0;i<h;i++)cin>>s[i];int len=s[0].length();for(int i=0;i<len;i++){b=s[0].substr(i,len-i);kmp();if(MAX>_size){_size=MAX;re1=s[0].substr(i,_size);}else if(MAX==_size){re2=s[0].substr(i,MAX);if(re2<re1)re1=re2;}}if(_size==0)cout<<"IDENTITY LOST\n";else cout<<re1<<endl;}return 0;}

POJ 3080 Blue Jeans

代码:

#include <iostream>#include <string>using namespace std;const int len=60;int num,m,p[60],MAX;string s[10],b;void getp(){p[0]=-1;int j=-1;for(int i=1;i<m;i++){while(j>-1&&b[j+1]!=b[i]) j=p[j];if(b[j+1]==b[i]) j+=1;p[i]=j;}}int kmp(){int curml;m=b.size();getp();MAX=60;for(int k=1;k<num;k++){curml=0;int j=-1;for(int i=0;i<len;i++){while(j>-1&&b[j+1]!=s[k][i])j=p[j];if(b[j+1]==s[k][i])j++;if(j+1==m){curml=m;break;}if(j+1>curml)curml=j+1;}if(curml<MAX)MAX=curml;}return MAX;}int main(){int t,k,mlen;string str1,str2;cin>>t;while(t--){mlen=0;str1="";cin>>num;for(int i=0;i<num;i++)cin>>s[i];for(int i=0;i<len;i++){b=s[0].substr(i,len-i);k=kmp();if(k>mlen){mlen=k;str1=s[0].substr(i,k);}else if(k==mlen){str2=s[0].substr(i,k);if(str2<str1)str1=str2;}}if(str1.length()<3)cout<<"no significant commonalities"<<endl;else cout<<str1<<endl;}return 0;}