马拉车

马拉车只能处理连续回文

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

// 标准马拉车:只找一个最长回文子串
string findLongestPalindromicSubstring(string s) {
    if (s.empty()) return "";
    
    string t = "#";
    for (char c : s) {
        t += c;
        t += '#';
    }
    
    int n = t.length();
    vector<int> p(n, 0);
    int center = 0, right = 0;
    int maxCenter = 0, maxLen = 0;
    
    for (int i = 0; i < n; i++) {
        if (i < right) {
            p[i] = min(right - i, p[2 * center - i]);
        }
        
        while (i - p[i] - 1 >= 0 && i + p[i] + 1 < n && 
               t[i - p[i] - 1] == t[i + p[i] + 1]) {
            p[i]++;
        }
        
        if (i + p[i] > right) {
            center = i;
            right = i + p[i];
        }
        
        // 关键:记录最长回文的中心位置
        if (p[i] > maxLen) {
            maxLen = p[i];
            maxCenter = i;
        }
    }
    
    int start = (maxCenter - maxLen) / 2;
    return s.substr(start, maxLen);
}

int main() {
    vector<string> testCases = {
        "babad",
        "cbbd", 
        "a",
        "abc",
        "aaa",
        "abacaba"
    };
    
    for (string s : testCases) {
        string result = findLongestPalindromicSubstring(s);
        cout << "字符串: \"" << s << "\"" << endl;
        cout << "最长回文子串: \"" << result << "\"" << endl;
        cout << "长度: " << result.length() << endl;
        cout << "------------------------" << endl;
    }
    
    return 0;
}

马拉车储存所有回文子串

vector<string> findAllLongestPalindromicSubstringsV2(string s) {
    if (s.empty()) return {""};

    // 预处理
    string t = "#";
    for (char c : s) {
        t += c;
        t += '#';
    }

    int n = t.length();
    vector<int> p(n, 0);
    int center = 0, right = 0;
    int maxLen = 0;

    // 第一步:执行标准马拉车算法
    for (int i = 0; i < n; i++) {
        if (i < right) {
            p[i] = min(right - i, p[2 * center - i]);
        }

        while (i - p[i] - 1 >= 0 && i + p[i] + 1 < n &&
               t[i - p[i] - 1] == t[i + p[i] + 1]) {
            p[i]++;
        }

        if (i + p[i] > right) {
            center = i;
            right = i + p[i];
        }

        maxLen = max(maxLen, p[i]);
    }

    // 第二步:收集所有最长回文子串
    vector<string> result;
    for (int i = 0; i < n; i++) {
        if (p[i] == maxLen) {
            int start = (i - p[i]) / 2;
            string palindrome = s.substr(start, maxLen);
            // 去重
            if (find(result.begin(), result.end(), palindrome) == result.end()) {
                result.push_back(palindrome);
            }
        }
    }

    return result;
}
posted @ 2025-11-12 23:05  miao-jc  阅读(3)  评论(0)    收藏  举报