【代码超详解】POJ 3080 Blue Jeans(暴力枚举 + KMP 匹配,0 ms)

一、题目描述

在这里插入图片描述

二、算法分析说明与代码编写指导

KMP 模板

由于字符串长度只有 60,要找出在所有字符串中都出现的最长子串,只需要取任意一个(这里取最先输入的一个)字符串,从短到长枚举其全部子串,然后进行 KMP 算法,只要有匹配,且字典序比已知的该长度的符合要求的字串小,就将输出结果替换为新找到的串。
实现时需要注意,在本代码中,最后输出的是字符串 R。每个长度的字典序最小的符合要求的子串暂时先存储在 r 中。用 strcmp 比较字典序。

三、AC 代码(0 ms)

#include<cstdio>
#include<cstring>
#include<algorithm>
#pragma warning(disable:4996)
template<class _NTy> inline void getnext(const char* const _Pattern, _NTy* const _Next, const size_t& _PatternLen) {
	size_t i = 1; _NTy j = 0; _Next[1] = 0;
	while (i <= _PatternLen) {
		if (j == 0 || _Pattern[i] == _Pattern[j]) { ++i, ++j, _Next[i] = j; }
		else j = _Next[j];
	}
}//The index of the head of _Pattern string is 1.
template<class _NTy> inline unsigned KMP(const char* const _Target, const char* const _Pattern, _NTy* const _Next, const size_t& _TargetLen, const size_t& _PatternLen) {
	size_t i = 1; _NTy j = 1;
	_Next[1] = 0, getnext(_Pattern, _Next, _PatternLen);
	while (i <= _TargetLen) {
		if (j == 0 || _Target[i] == _Pattern[j]) { ++i, ++j; }
		else j = _Next[j];
		if (j > _PatternLen) { return 1; }
	}
	return 0;
}//The index of the head of _Pattern string is 1.
const size_t L = 60; char s[10][L + 2], t[L + 2], r[L + 2], R[L + 2]; unsigned next[L + 2], m, n, a; bool ok;
int main() {
	scanf("%u", &n); ++n;
	while (--n) {
		scanf("%u", &m); std::fill(R, R + L, 0); a = 0;
		for (unsigned i = 0; i < m; ++i) { getchar(); fgets(s[i] + 1, L + 1, stdin); }
		for (size_t l = 1; l <= L; ++l) {
			std::fill(r, r + L, 'z');
			for (size_t i = 1, im = L - l + 1; i <= im; ++i) {
				strncpy(t + 1, s[0] + i, l); ok = true;
				for (unsigned j = 1; j < m; ++j) {
					if (KMP<unsigned>(s[j], t, next, L, l) == 0) { ok = false; break; }
				}
				if (ok == true && strcmp(t + 1, r) < 0) { strncpy(r, t + 1, l); a = l; }
			}
			if (r[0] != 'z')strncpy(R, r, l);
		}
		if (a < 3)puts("no significant commonalities");
		else puts(R);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值