zoukankan      html  css  js  c++  java
  • Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记

    DECLARATION

    引用来源:https://www.cnblogs.com/grandyang/p/4475985.html

    CONTENT

    用途:寻找一个字符串的最长回文子串
    时间复杂度:O(N)
    算法步骤
    1.添加特殊字符

    由于回文串的长度可奇可偶,比如"bob"是奇数形式的回文,"noon"就是偶数形式的回文,马拉车算法的第一步是预处理,做法是在每一个字符的左右都加上一个特殊字符,比如加上'#',那么

    bob --> #b#o#b#

    noon --> #n#o#o#n#

    这样做的好处是不论原字符串是奇数还是偶数个,处理之后得到的字符串的个数都是奇数个,这样就不用分情况讨论了,而可以一起搞定。

    2.求每个回文子串的半径

    我们还需要和处理后的字符串t等长的数组p,其中p[i]表示以t[i]字符为中心的回文子串的半径,若p[i] = 1,则该回文子串就是t[i]本身。

    最长子串的长度是半径减1,起始位置是中间位置减去半径再除以2。

    如何求p数组,需要新增两个辅助变量mxid,其中id为能延伸到最右端的位置的那个回文子串的中心点位置,mx是回文串能延伸到的最右端的位置,这个算法的最核心的一行如下:
    p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;

    代码实现
    Leetcode #5

    class Solution {
    public:
        string longestPalindrome(string s) {
            // Insert '#'
            string t = "$#";
            for (int i = 0; i < s.size(); ++i) {
                t += s[i];
                t += "#";
            }
            // Process t
            vector<int> p(t.size(), 0);
            int mx = 0, id = 0, resLen = 0, resCenter = 0;
            for (int i = 1; i < t.size(); ++i) {
                p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
                while (t[i + p[i]] == t[i - p[i]]) ++p[i];
                if (mx < i + p[i]) { //update mx & id
                    mx = i + p[i];
                    id = i;
                }
                if (resLen < p[i]) { //update resLen & resCenter
                    resLen = p[i];
                    resCenter = i;
                }
            }
            return s.substr((resCenter - resLen) / 2, resLen - 1);
        }
    };
    
  • 相关阅读:
    课程评价
    6.1-6.7 第十六周总结
    5.31 软件开发日志
    5.25-5.31 第十五周总结
    5.30 软件开发日志
    5.29 软件开发日志
    5.28 软件开发日志
    对搜狗输入法的评价
    找水王
    用户模板/用户场景
  • 原文地址:https://www.cnblogs.com/NeilThang/p/10105874.html
Copyright © 2011-2022 走看看