POJ-3080 -求n个字符串最长公共子串-暴力枚举

。。。。数据太小,就直接用暴力n^3的做法了

以第一个串为主,枚举它的所有子串,看某个子串是否为其余所有字符串的 子串,如果是,则为公共子串


然后合法的子串里面找一个最长的,字典序最小的。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std; 
const int mod=1000000007;
int min(int a,int b)
{return a<b?a:b;}
int max(int a,int b)
{return a>b?a:b;}

char tm[15][100];
char first[100];
char ans2[100][100];
int cmp(char *s1,char* s2)
{
	return strcmp(s1,s2)<0;
}
int val[100];
void getnext(char *s,int len)
{
	int i=1,j=0;
	val[1]=0;
	while(i<len)
	{
		if (j==0||s[i]==s[j])
		{i++;j++;val[i]=j;}
		else
			j=val[j];
	}
}
int kmp(char *s1,char *s2,int len1)//s1-子串,s2-字典
{
	int len2=strlen(s2+1);
	int i=1,j=1;
	while(i<=len1&&j<=len2)
	{
		if (i==0||s1[i]==s2[j])
		{i++,j++;}
		else
			i=val[i];
	}
	if (i>len1)
		return i-len1;
	else
		return -1;
}
struct node
{
	int i,j;
	node(){}
	node(int a,int b)
	{i=a;j=b;}
};
node ans[60*60*2];

int main()
{

	
	int t;cin>>t;
	while(t--)
	{
	 
		int maxlen=0;
		int maxnum=0;
		int m;
		int i,j;
		cin>>m;
		scanf("%s",first+1);
		int len1=strlen(first+1);
		for (i=1;i<=m-1;i++)
		{
			scanf("%s",tm[i]+1);
		}
	 
		for (i=1;i<=len1;i++)
		{
			for (j=i;j<=len1;j++)
			{ 
				if (j-i+1<maxlen) continue;
				char sub[100];
				int k;
				for (k=i;k<=j;k++)
					sub[k-i+1]=first[k];
				sub[j-i+2]=0;
				getnext(sub,j-i+1);
				int ret;
				int flag=0;
 				for (int h=1;h<=m-1;h++)
				{ 
					ret=kmp(sub,tm[h],j-i+1);
					if (ret==-1)
					{flag=1;break;}  
				}
				if (!flag)
				{
					ans[++maxnum]=node(i,j);
					if (j-i+1>maxlen) maxlen=j-i+1; 
				}
			}
		
		}
		  for (i=1;i<=maxnum;i++)
		  {
			  for(int k=ans[i].i;k<=ans[i].j;k++)
				  ans2[i][k-ans[i].i+1]=first[k];
			  ans2[i][ans[i].j-ans[i].i+2]=0;
		  }
		   int mini=maxnum;
		   int tmp_len=ans[maxnum].j-ans[maxnum].i+1;
		   for (i=1;i<=maxnum;i++)
		   {
			   if (ans[i].j-ans[i].i+1!=tmp_len ) continue;
				if (strcmp(ans2[i]+1,ans2[mini]+1)<0  )
					mini=i;
		   }
		   if (ans[mini].j-ans[mini].i+1<3)
			   printf("no significant commonalities\n");
		   else
			printf("%s\n",ans2[mini]+1);
	}
		
		
		return 0;
		
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值