POJ3080 && POJ 3450

题意: 给定m个串,让你找出它们的最长公共子串

思路: 先二分串的长度,枚举该长度的串(可以从第一个串里找),看该长度是否合法,(就是用这个长度的所有串去匹配给定的 第 2 - m 个串 为提高效率,用kmp)然后得到一个最大长度,再在该长度下寻找一个字典序最小的解即可

POJ3450代码(3080类似)

/*************************************************************************
    > File Name: poj3450.cpp
    > Author: ALex
    > Mail: [email protected]
    > Created Time: 2015年02月02日 星期一 20时14分57秒
 ************************************************************************/

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

const int N = 222;
int next[N];
char str[N];
char mat[4010][N];
char p[N];
int m;

void get_next ()
{
	int len = strlen (str);
	next[0] = -1;
	int j = 0, k = -1;
	while (j < len)
	{
		if (k == -1 || str[k] == str[j])
		{
			++k;
			++j;
			next[j] = k;
		}
		else
		{
			k = next[k];
		}
	}
}

bool match_ok (int s)
{
	int i = 0, j = 0;
	int lens = strlen (mat[s]);
	int lent = strlen (str);
	while (i < lens && j < lent)
	{
		if (j == -1 || str[j] == mat[s][i])
		{
			++i;
			++j;
		}
		else
		{
			j = next[j];
		}
	}
	if (j == lent)
	{
		return 1;
	}
	return 0;
}

bool solve (int L)
{
	bool flag = false;
	int len = strlen (mat[1]);
	for (int i = 0; i + L - 1 < len; ++i)
	{
		for (int j = i; j < i + L; ++j)
		{
			str[j - i] = mat[1][j];
		}
		str[L] = '\0';
		get_next ();
		bool tmp = true;
		for (int j = 2; j <= m; ++j)
		{
			if (!match_ok (j))
			{
				tmp = false;
				break;
			}
		}
		if (tmp)
		{
			flag = true;
			break;
		}
	}
	return flag;
}

void Binsearch ()
{
	int len = strlen (mat[1]);
	int l = 1, r = len, mid, ans = -1;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if (solve (mid))
		{
			ans = mid;
			l = mid + 1;
		}
		else
		{
			r = mid - 1;
		}
	}
	if (ans == -1)
	{
		printf("IDENTITY LOST\n");
		return;
	}
	bool flag = false;
	for (int i = 0; i + ans <= len; ++i)
	{
		for (int j = i; j < i + ans; ++j)
		{
			str[j - i] = mat[1][j];
		}
		str[ans] = '\0';
		get_next ();
		bool x = true;
		for (int j = 2; j <= m; ++j)
		{
			if (!match_ok (j))
			{
				x = false;
				break;
			}
		}
		if (x)
		{
			if (!flag)
			{
				flag = true;
				strcpy (p, str);
			}
			else
			{
				if (strcmp (p, str) > 0)
				{
					strcpy (p, str);
				}
			}
		}
	}
	printf("%s\n", p);
}

int main ()
{
	while (~scanf("%d", &m), m)
	{
		for (int i = 1; i <= m; ++i)
		{
			scanf("%s", mat[i]);
		}
		Binsearch ();
	}
	return 0;
}
时间: 2024-10-14 12:20:23

POJ3080 && POJ 3450的相关文章

POJ 3450 Corporate Identity KMP题解

本题要求求一组字符串的最长公共子串,其实是灵活运用KMP快速求最长前缀. 注意肯爹的题意:要求按照字典顺序输出. 还有要提醒的就是:有人也是用KMP来解这道题,但是很多人都把KMP当成暴力法来用了,没有真正处理好细节,发挥KMP的作用.而通常这些人都大喊什么暴力法可以解决本题,没错,的确暴力法是可以解决本题的,本题的数据不大,但是请不要把KMP挂上去,然后写成暴力法了,那样会误导多少后来人啊. 建议可以主要参考我的getLongestPre这个函数,看看是如何计算最长前缀的. 怎么判断你是否把本

字符串截取模板 &amp;&amp; POJ 3450、3080 ( 暴力枚举子串 &amp;&amp; KMP匹配 )

//截取字符串 ch 的 st~en 这一段子串返回子串的首地址 //注意用完需要根据需要最后free()掉 char* substring(char* ch,int st,int en) { int length = en - st + 1; char* pch=ch; char* subch=(char*)malloc(length+1); pch=pch+st; for(int i=0;i<length;i++) subch[i]=*(pch++); subch[length]='\0';

POJ 3450 Corporate Identity(KMP)

[题目链接] http://poj.org/problem?id=3450 [题目大意] 求k个字符串的最长公共子串,如果有多个答案,则输出字典序最小的. [题解] 我们对第一个串的每一个后缀和其余所有串做kmp,取匹配最小值的最大值就是答案. [代码] #include <cstring> #include <cstdio> #include <algorithm> const int N=4050,M=210; using namespace std; int nx

POJ - 3450

题目链接:http://poj.org/problem?id=3450 Corporate Identity Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8549   Accepted: 2856 Description Beside other services, ACM helps companies to clearly state their "corporate identity", which i

POJ 3450 Corporate Identity 求所有字符的最长公共子串

Description Beside other services, ACM helps companies to clearly state their "corporate identity", which includes company logo but also other signs, like trademarks. One of such companies is Internet Building Masters (IBM), which has recently a

kuangbin带你飞 后缀数组 题解

2份模板 DC3 . 空间复杂度O3N 时间复杂度On #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb)) #define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2) const int MAXN = 300010; const int MAXM = 100010; char input[MAXM]; int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAX

POJ 题目3450 Corporate Identity(KMP 暴力)

Corporate Identity Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5493   Accepted: 2015 Description Beside other services, ACM helps companies to clearly state their "corporate identity", which includes company logo but also other

POJ题目推荐(转载)

POJ推荐50题1.标记“难”和“稍难”的题目可以看看,思考一下,不做要求,当然有能力的同学可以直接切掉.2.标记为A and B的题目是比较相似的题目,建议大家两个一起做,可以对比总结,且二者算作一个题目.3.列表中大约有70个题目.大家选做其中的50道,且每类题目有最低数量限制.4.这里不少题目在BUPT ACM FTP上面都有代码,请大家合理利用资源.5.50个题目要求每个题目都要写总结,养成良好的习惯.6.这个列表的目的在于让大家对各个方面的算法有个了解,也许要求有些苛刻,教条,请大家谅

POJ分类

初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算法: (1)图的深度优先遍历和广度优先遍历. (2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra) (poj1860,poj3259,p