专栏文章

题解:AT_abc398_f [ABC398F] ABCBA

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minjtd4v
此快照首次捕获于
2025/12/02 03:34
3 个月前
此快照最后确认于
2025/12/02 03:34
3 个月前
查看原文
四倍经验:P9606,UVA11475,SP4103。

题目大意

给出一个字符串 ss,求以 ss 为前缀的最短回文串。
1s5×1051 \le |s| \le 5 \times 10 ^ 5

题目分析

解法一:KMP

分析

ss 反转后为 tt。此时,t+st + s 必为回文串。接下来我们让这个回文串最短。
s=TREEs = \texttt{TREE} 举例,此时 t=EERTt = \texttt{EERT},那么 t+s=EERTTREEt + s = \texttt{EERTTREE},那么这里的两个 E\texttt{E} 就是多余的,我们可以把这两个删掉,而这两个就是 t+st + s 的最长相同前缀后缀,那 KMP 即可解决。

code

CPP
#include <bits/stdc++.h>
#define ft first
#define sd second
#define endl '\n'
#define pb push_back
#define md make_pair
#define gc() getchar()
#define pc(ch) putchar(ch)
#define umap unordered_map
#define pque priority_queue
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 bint;
typedef pair<int, int> pii;
typedef pair<pii, int> pi1;
typedef pair<pii, pii> pi2;
const ll INF = 0x3f3f3f3f;
const db Pi = acos(-1.0);
inline ll read()
{
	ll res = 0, f = 1; char ch = gc();
	while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : f), ch = gc();
	while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + (ch ^ 48), ch = gc();
	return res * f;
}
inline void write(ll x)
{
	if (x < 0) x = -x, pc('-');
	if (x > 9) write(x / 10);
	pc(x % 10 + '0');
}
inline void writech(ll x, char ch) { write(x), pc(ch); }
const int N = 5e5 + 5;
int p[N << 1];
int main()
{
	string s; cin >> s;
	string t = s;
	reverse(t.begin(), t.end());
	string b = ' ' + t + ' ' + s;
	p[1] = 0;
	int l = b.size() - 1;
	for (int i = 1, j = 0; i < l; i++)
	{
		while (j && b[j + 1] != b[i + 1]) j = p[j];
		if (b[j + 1] == b[i + 1]) j++;
		p[i + 1] = j;
	}
	int k = p[l];
	string ans = s; l = t.size();
	for (int i = k; i < l; i++) ans += t[i];
	cout << ans << endl;
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...