ABB 洛谷 - P9606 最长回文后缀

ABB 洛谷 - P9606 最长回文后缀_第1张图片

题目大意

求使给定字符串变成回文串,需要在末尾加入字母的最少数量

题目分析

对于给定的字符串分析:如果字符串末尾为长度为k的回文串,那么需要在末尾加入字母的最少数量,则为n-k,那么,这道题就转化成了,求字符串的最大回文后缀。

设字符串s的反转为s_rev,那么s的后缀为s_rev的前缀,将二者拼接在一起,中间用#作为分隔符号,得到一个新的字符串s’,那么求s的最大回文后缀等价于求s'的最长相同前后缀,KMP算法。将用n减去求得的next数组的最后一个数,即为答案。

代码实现

#include 
#include 
#include 
#include 
using namespace std;
int longest_suffix_lindrome(const string& s) {//最长后缀回文
    string rev = s;
    reverse(rev.begin(), rev.end());//反转字符串
    string tmp = rev + "#" + s;//将反转后的字符串与原字符串拼接,用'#'作为分隔符
    vector next(tmp.size(), 0);
    for (int i = 1; i < tmp.size(); ++i) {//KMP求最大相同前后缀
        int j = next[i - 1];
        while (j > 0 && tmp[i] != tmp[j])
            j = next[j - 1];
        if (tmp[i] == tmp[j])
            ++j;
        next[i] = j;
    }
    return next.back();
}
int main() {
    int n;
    string s;
    cin >> n >> s;
    cout << n - longest_suffix_lindrome(s) << endl;
    return 0;
}

你可能感兴趣的:(算法)