KMP---POJ3080(暴力+匹配)

题意:求n个字符串的长公共子序列;

题解:暴力出第一个序列的字串,最多有60*60种,然后根据字串进行匹配。

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long 
const int maxn=1e5+10;
string str[50]; 
int F[maxn];
void init(string s)//获取next数组,我比较喜欢用F
{
   memset(F,-1,sizeof(F));
   for(int i=1;i<s.size();i++)
   {
   	int j=F[i-1];
   	while(s[j+1]!=s[i]&&j>=0)
   	j=F[j];
   	if(s[j+1]==s[i])
    F[i]=j+1;
   }
} 
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{   int n;
	    scanf("%d",&n);
	    for(int i=0;i<n;i++)cin>>str[i];
	    string ans="";
		for(int i=0;i<str[0].size();i++)//枚举起点 
		{   if(str[0].size()-i<ans.size())break;//这一句话一定要有,相当于剪枝。
                     //当当前答案已经走比后面还长的序列了,就不用继续枚举了。
			for(int j=2;j<=str[0].size()-i;j++)//枚举长度。
			{
				bool flag=true;
				string res=str[0].substr(i,j);
				//cout<<res<<endl;
				init(res);
			//	cout<<res<<endl;
			for(int i=1;i<n;i++)//枚举每一个字符串 
			{ 
			    bool ok=false;
				int u=0,d=0;
				while(u<str[i].size())//匹配每一个字符串 
				{
					if(str[i][u]==res[d])
					{
						u++;
						d++;
						if(d==res.size())//若匹配成功 
						{
							ok=true;
							break;
						}
					}
					else//否则继续匹配 
					{
						if(d==0)u++;
						else d=F[d-1]+1;
					}
				}
				if(!ok)//如果没有匹配成功 
				    {
			        flag=false;
			        break;
				    }
		    }
		    if(flag)//若匹配成功了
		    {
		    	if(res.size()>ans.size())ans=res;
		    	if(res.size()==ans.size()&&ans>res)ans=res;
			}
			}
		}
		if(ans.size()<3)cout<<"no significant commonalities"<<endl;
		else cout<<ans<<endl;
	}
}
发布了67 篇原创文章 · 获赞 4 · 访问量 4807

猜你喜欢

转载自blog.csdn.net/weixin_44203780/article/details/93530019