ACM Note No.8: Manacher


ACM Note No.8: Manacher

马拉车算法可以用于解决最长回文子串的问题

当然也可以通过对下文的回文半径数组P求和,以获得回文子串的总数

#include <bits/stdc++.h>
using namespace std;
string manacher(const string& s) {
    // 步骤 1: 在原字符串中插入特殊字符 '#',以统一处理奇偶回文串
    string T = "#";
    for (char c : s) {
        T += c;
        T += "#";
    }
    int n = T.length();
    // 回文半径数组
    vector<int> P(n, 0);  
    // 当前回文中心和右边界
    int C = 0, R = 0;
    // 最长回文的长度和中心位置
    int maxLen = 0, centerIndex = 0; 
    // 步骤 2: 遍历字符串进行回文扩展
    for (int i = 0; i < n; ++i) {
        // 步骤 3: 利用对称性初始化P[i]
        if (i < R) {
            P[i] = min(R - i, P[2 * C - i]);  // 对称位置的回文半径
        }
        // 步骤 4: 尝试扩展回文
        while (i + P[i] + 1 < n && i - P[i] - 1 >= 0 && T[i + P[i] + 1] == T[i - P[i] - 1]) {
            P[i]++;
        }
        // 步骤 5: 更新C和R
        if (i + P[i] > R) {
            C = i;
            R = i + P[i];
        }
        // 步骤 6: 更新最大回文长度和中心
        if (P[i] > maxLen) {
            maxLen = P[i];
            centerIndex = i;
        }
    }
    // 步骤 7: 从回文半径数组中恢复最长回文子串
    // 计算原字符串中的起始位置
    int start = (centerIndex - maxLen) / 2;  
    return s.substr(start, maxLen);
}

int main() {
    string s;
    cin >> s;
    string result = manacher(s);
    cout << "Longest Loop String: " << result << endl;
    return 0;
}

声明:Blog|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - ACM Note No.8: Manacher