• [LeetCode] Longest Palindromic Substring(manacher algorithm)


    Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

    方法:

    Manacher's algorithm,具体看这里http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

    或者有比较好的博客:http://blog.csdn.net/ggggiqnypgjg/article/details/6645824

     编码步骤如下:

    1)在s字符串字符间添加特殊字符,使得原s字符串无论是奇数长度还是偶数长度,都变为奇数长度处理,变化后的字符串记为sNew;

    2)用数组P[id]记录以字符sNew[id]为中心的最长回文串的半长度;

    前两步如下所示:

          s  :             w       a      a      b       w

      sNew: $      #  w  #  a  #  a  #  b  #  w  #

      P[id] :   1      1      2      1      2      3      2      1      2     1       2      1

    3) 在O(n)时间求出数组P,然后遍历一遍P,可以由sNew中恢复出最长回文串。

    用 O(n)时间求出数组P的方法,见代码,里面有详细注释。

    class Solution {
    public:
        string longestPalindrome(string s) {
            string result;
            string sNew(1,'$');
            sNew.push_back('#');
            int len = s.size();
            if(len==0)
                return result;
            else if(len==1)
                return s;
            for(int i=0;i<len;i++){
                sNew.push_back(s[i]);
                sNew.push_back('#');
            }//end for
    
            int lenNew = 2*(len+1);
            vector<int> P(lenNew,1);
            Pk(P,lenNew,sNew);
            vector<int> P0(P);
            sort(P0.begin(),P0.end());
            int maxlen = P0[lenNew-1];
            int index;
            for( index=0;index<lenNew;index++){
                if(P[index]==maxlen)
                    break;
            }
            if(sNew[index]!='#'){
                result.push_back(sNew[index]);
                maxlen -= 2;
                index += 2;
            }else{
                maxlen -= 1;
                index += 1;
    
            }
            while(maxlen>0){
                result.insert(result.begin(),sNew[index]);
                result.push_back(sNew[index]);
                index += 2;
                maxlen -= 2;
            }
            return result;
        }
    private:
        void Pk(vector<int> &P,int n,string s){
             int i,mx=0,id;//id是对称中心点的下标,mx是对称段的上届
             for(i=1;i<n;i++){
                if(mx > i)
                    P[i] = min(P[2*id-i],mx-i);//j=2*id-i,j是i关于id的对称点(和底下的while语句合起来,使得P[i]不用多重复计算)
                else
                    P[i]=1;
    
                while(s[i+P[i]]==s[i-P[i]])//计算以i点为中心的最大回文段,将最大回文长度的一半大小记录在P[i]中
                    P[i]++;
                if(P[i]+i>mx){
                   mx=P[i]+i;//更新当前点的对称段上届mx
                   id = i;//更新当前对称中心点的下标id
                }
             }//end for    
        }//end func
    };    
  • 相关阅读:
    多线程中,上锁的理解
    sql server 2008 联机丛书
    序列化是线程安全的么
    对象化下的编程——字段
    Dic实现工厂模式
    design principle:java 回调与委派/委托机制(转)
    风筝数据结构学习笔记(2)后序遍历二叉树(非递归)
    风筝数据结构学习笔记(1)利用链式存储结构和递归构建二叉树
    吕震宇老师《设计模式系列》
    吕震宇老师《设计模式随笔系列》
  • 原文地址:https://www.cnblogs.com/Xylophone/p/3937700.html
Copyright © 2020-2023  润新知