马拉车算法

马拉车算法查找 字符串的最大回文子串。
其算法本质上是中心扩展法。


中心扩展法

vector<int> v(strLen,0); //v[i] 是指以i为中心的回文字符串长度的半径
for (int i = 1; i < strLen - 1; i++)
    while (str[i + 1 + v[i]] == str[i - 1 - v[i]]) ++v[i];//不考虑越界

而马拉车利用回文的对称性避免多余的计算
核心算法如图所示

是的,最核心的就这个了。


剩下的是解决回文字符串长度是奇数还是偶数(利用插入其它字符)
以及如何更新可利用的A点(当可利用的A点范围比最新的 “A"点 要小时,就更新A点)


附poj 3974 AC代码

int mlc(string &str) {
    if (str.size() == 0) return 0;
    string newStr;
    newStr.push_back('^');
    newStr.push_back('#');
    int len = str.size();
    for (int i = 0; i < len; i++) {
        newStr.push_back(str[i]);
        newStr.push_back('#');
    }
    newStr.push_back('$');
    int newLen = newStr.size();
    vector<int> v(newLen,0);
    int C = 0, R = 0;
    for (int i = 1; i < newLen - 1; i++) {
        int i_mirror = 2 * C - i;
        if (R > i) 
            v[i] = min(R - i, v[i_mirror]);
        while (newStr[i + 1 + v[i]] == newStr[i - 1 - v[i]]) {
            ++v[i];
        }
        if (i + v[i] > R) {
            C = i;
            R = i + v[i];
        }
    }
    int ret = 1;
    for (int i = 1; i < newLen - 1; i++) {
        ret = max(ret, v[i]);
    }
    return ret;
}

int main() {
    string str;
    int idx = 0;
    for (; ; ) {
        cin >> str;
        if (str == "END") {
            break;
        }
        int len = mlc(str);
        cout << "Case " << ++idx << ": " << len << endl;
    }
    return 0;
}
posted @ 2021-02-24 19:55  传说中的水牛  阅读(84)  评论(0编辑  收藏  举报