专栏文章

题解:AT_abc398_f [ABC398F] ABCBA

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

文章操作

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

当前评论
0 条
当前快照
1 份
快照标识符
@mipua6ry
此快照首次捕获于
2025/12/03 18:03
3 个月前
此快照最后确认于
2025/12/03 18:03
3 个月前
查看原文

KMP 板子题

题意不能再简述了,要想让添加上后缀形成的的回文字符串最短,我们要充分利用原字符串自身形成的回文子串。具体来说就是找原字符串的一个最长回文后缀。
将原字符串 ss 的反转串 s2s2 拼接到 ss 之前,也就是对 s2+ss2+s 做 kmp,得到的 nextnext 数组最后一个数就是匹配的最长回文后缀长度。
注意两个串拼接起来可能会发生重叠,比如 AA,变为 AAAA,得到的最长回文后缀长度应该是 2,但是 nextnext 数组会得到 4,所以我们实际处理 s2+"#"+ss2+"\#"+s 串来解决这个问题。
找到最长回文后缀后,将未形成回文的前半部分反转拼接到原字符串末尾即可。
代码如下:
CPP
int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    string s;
    cin >> s;
    int n = s.size();
    string s2 = s;
    std::reverse(s2.begin(), s2.end());
    string tmp = s2 + "#" + s;
    int siz = tmp.size(), cn = 0;
    std::vector<int> next(siz, 0);
    for (int i = 1; i < siz; ++i) {
        while (cn > 0 && tmp[i] != tmp[cn]) {
            cn = next[cn - 1];
        }
        if (tmp[i] == tmp[cn]) {
            cn++;
        }
        next[i] = cn;
    }
    int k = next.back();
    string ans = s.substr(0, n - k);
    reverse(ans.begin(), ans.end());
    cout << s + ans << "\n";
    return 0;
}

评论

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

正在加载评论...