• 5_Longest Palindromic Substring(Manacher) --LeetCode


    参考:https://www.felix021.com/blog/read.php?2040https://segmentfault.com/a/1190000002991199 做了修改。

      首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一个特殊的符号。比如 abba 变成 #a#b#b#a#, aba变成 #a#b#a#。 为了进一步减少编码的复杂度,可以在字符串的开始加入另一个特殊字符,这样就不用特殊处理越界问题,比如$#a#b#a#(注意,下面的代码是用C语言写就,由于C语言规范还要求字符串末尾有一个''所以正好OK,但其他语言可能会导致越界)。
    下面以字符串12212321为例,经过上一步,变成了 S[] = "$#1#2#2#1#2#3#2#1#";

      原帖中需要用一个数组 P[i] 来记录以字符S[i]为中心的最长回文子串向左/右扩张的长度(包括S[i],也就是把该回文串“对折”以后的长度),比如S和P的对应关系:

      S  #  1  #  2  #  2  #  1  #  2  #  3  #  2  #  1  #
      P  1  2  1  2  5  2  1  4  1  2  1  6  1  2  1  2  1
      (p.s. 可以看出,P[i]-1正好是原字符串中回文串的总长度)

    但我不采用以上的做法,我的算法思想如下:

    从S的下标1开始遍历到下标S.length()-2做如下操作

    1) 假设偏移量为offset, 用一个while循环控制在对比 S[i-offset] 和第 S[i+offset] 的字符是否相等,每次循环offset自增,直到S[i-offset] 不等于S[i+offset] 或者i-offset<1或者i+offset>S.length()-1跳出循环。

    2) 使用一个变量maxlength记录最长回文子串向左/右扩张的长度,以及一个maxidx记录当前最大回文串的中心位置,判断当前的offset与maxlength的大小,取较大赋值给maxlength。

    3) 根据maxidx找到最大回文的中心位置,再根据其maxlength计算出回文串的起始位置以及长度。再使用substr()方法将回文串截取出来。如str.substr(maxidx-maxlength+1,2*maxlength-1);

    4) 去掉其中的 ‘#’字符,就得到回文串。

    代码如下:

    class Solution {
    public:
        string longestPalindrome(string s) {
            //小于1的字符串免处理,直接返回
            if(s.size()<=1){
                return s;
            }
            
            int len = s.size();
            string str = preProcess(s);
            //使用一个变量maxlength记录最长回文子串向左/右扩张的长度,以及一个maxidx记录当前最大回文串的中心位置,判断当前的offset与maxlength的大小,取较大赋值给maxlength。
            int offset,maxidx = 0,maxlength = 0;
            for(int cur = 1; cur < str.size()-1; ++cur){
                //查找最大回文串
                offset = 0;
                while(cur-offset>=1 && cur+offset < str.size() && str[cur-offset] == str[cur+offset]) {
                    ++offset;
                }
                
                //更新maxlength
                if(maxlength < offset){
                    maxlength = offset;
                    maxidx = cur;
                }  
            }
            
            //截取最长回文串
            string longeststr = str.substr(maxidx-maxlength+1,2*maxlength-1);
            //去除"#"字符
            string result = "";
            for(int i = 0; i<longeststr.size();i++){
                if(longeststr[i]!='#')
                    result+=longeststr[i];
            }
            return result;
        }
    private:
        //预处理
        string preProcess(string s){
            string str = "$";
            int len = s.size();
            for(int i = 0; i<len; i++)
            {
                str+="#";
                str+=s[i];
            }
            str+="#";
            return str;
        }
    };
  • 相关阅读:
    Codeforces Round #394 (Div. 2) A. Dasha and Stairs
    HDU 1410 PK武林盟主
    HDU 3362 Fix(状压dp)
    P678-vect2.cpp
    Qt5获取本机网络信息
    Qt5标准文件对话框类
    nRF52832无法加载协议栈文件
    Debug记录(1)
    大小端模式
    nRF52832的SAADC
  • 原文地址:https://www.cnblogs.com/houjun/p/8494920.html
Copyright © 2020-2023  润新知