CF25E Test 题解

考虑枚举三个字符串的全排列,设为 x,y,zx,y,z

分类讨论:

  • yyxx 的子串:

    • zzxx 的子串,最短的长度为 xx 的长度。
    • 否则找到 zz 的最长前缀,满足其是 xx 的后缀。
  • 否则:

    • 找到 yy 的最长前缀,满足其是 xx 的后缀。
    • 设找到后拼起来的字符串为 pp。讨论 zzpp 的关系即可。

可以 KMP,也可以哈希。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
// 12323
const int N = 5e5 + 5;

using ull = unsigned long long;
string s[4];
int ans = 2e9;

ull powe[N], hash1[N], hash2[N], hash3[N], hash4[N];

int getans()
{
	hash1[0] = s[1][0] - 'a' + 1;
	hash2[0] = s[2][0] - 'a' + 1;
	hash3[0] = s[3][0] - 'a' + 1;
	for (int i = 1; i < s[1].size(); i++)
	{
		hash1[i] = hash1[i - 1] * 337 + (s[1][i] - 'a' + 1);
	}
	for (int i = 1; i < s[2].size(); i++)
	{
		hash2[i] = hash2[i - 1] * 337 + (s[2][i] - 'a' + 1);
	}
	for (int i = 1; i < s[3].size(); i++)
	{
		hash3[i] = hash3[i - 1] * 337 + (s[3][i] - 'a' + 1);
	}
	ull h1 = hash1[s[1].size() - 1], h2 = hash2[s[2].size() - 1], h3 = hash3[s[3].size() - 1];
	bool flag = 0;
	for (int i = 0; i + s[2].size() - 1 < s[1].size(); i++)
	{
		int l = i, r = i + s[2].size() - 1;
		ull subhash = hash1[r] - (l == 0 ? 0 : hash1[l - 1] * powe[r - l + 1]);
		if (subhash == h2)
		{
			flag = 1;
			break;
		}
	}
	if (flag)
	{
		bool flag2 = 0;
		for (int i = 0; i + s[3].size() - 1 < s[1].size(); i++)
		{
			int l = i, r = i + s[3].size() - 1;
			ull subhash = hash1[r] - (l == 0 ? 0 : hash1[l - 1] * powe[r - l + 1]);
			if (subhash == h3)
			{
				flag2 = 1;
				break;
			}
		}
		if (flag2) return s[1].size();
		int res = s[1].size() + s[3].size();
		for (int i = 1; i <= min(s[1].size(), s[3].size()); i++)
		{
			int l1 = 0, r1 = i - 1;
			int l2 = s[1].size() - i, r2 = s[1].size() - 1;
			ull hs1 = hash3[r1];
			ull hs2 = hash1[r2] - (l2 == 0 ? 0 : hash1[l2 - 1] * powe[r2 - l2 + 1]);
			if (hs1 == hs2) res = min(res, (int)(s[1].size() + s[3].size() - i));
		}
		return res;
	}
	else
	{
		string mn = s[1] + s[2];
		int res = s[1].size() + s[2].size();
		int p = 0;
		for (int i = 1; i <= min(s[1].size(), s[2].size()); i++)
		{
			int l1 = 0, r1 = i - 1;
			int l2 = s[1].size() - i, r2 = s[1].size() - 1;
			ull hs1 = hash2[r1];
			ull hs2 = hash1[r2] - (l2 == 0 ? 0 : hash1[l2 - 1] * powe[r2 - l2 + 1]);
			if (hs1 == hs2)
			{
				if ((int)(s[1].size() + s[2].size() - i) < res)
				{
					res = (s[1].size() + s[2].size() - i);
					p = i;
				}
			}
		}
		if (p)
		{
			mn = s[1].substr(0, s[1].size() - p) + s[2];
		}
		hash4[0] = mn[0] - 'a' + 1;
		for (int i = 1; i < mn.size(); i++)
		{
			hash4[i] = hash4[i - 1] * 337 + (mn[i] - 'a' + 1);
		}
		res = mn.size() + s[3].size();
		for (int i = 1; i <= min(mn.size(), s[3].size()); i++)
		{
			int l1 = 0, r1 = i - 1;
			int l2 = mn.size() - i, r2 = mn.size() - 1;
			ull hs1 = hash3[r1];
			ull hs2 = hash4[r2] - (l2 == 0 ? 0 : hash4[l2 - 1] * powe[r2 - l2 + 1]);
			if (hs1 == hs2)
			{
				res = min(res, (int)(mn.size() + s[3].size() - i));
			}
		}
		return res;
	}
}

int main()
{
	ios::sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr);
	powe[0] = 1;
	for (int i = 1; i < N; i++)
	{
		powe[i] = powe[i - 1] * 337;
	}
	cin >> s[1] >> s[2] >> s[3];
	sort(s + 1, s + 4);
	int res = 1e9;
	do
	{
		res = min(res, getans());
	} while (next_permutation(s + 1, s + 4));
	cout << res << "\n";
	return 0;
}
posted @   HappyBobb  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示