zoukankan      html  css  js  c++  java
  • leetcode--Longest Palindromic Substring

    1.题目描述

    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.

    2.解法分析

    拿到题目的一瞬间,我就想到了两个办法,但都看起来不是那么好的方法,方法一是求出输入串和输入串逆置串(就是将输入串逆序)的最长公共字串,这个算法很容易实现,但是时间复杂度过高,还有一种就是后缀数组的方法,求出最长后缀即可,但是这种方法比较麻烦。做了这么长时间的leetcode,我的经验告诉我这个题目应该会有更加精妙的解法,希望能理解。

    果不其然,网上是有另外一种算法的,这个算法深入挖掘了回文的性质,针对这个题目,最简单的算法莫过于遍历字符串的每一位,然后以每一位为中心,两边扩展来求最长的回文子串,这样做的时间复杂度当然是O(N2),那么在遍历的过程中,有没有方法利用之前得到的结果呢?

    答案是有的!网上传有一种Manacher算法--O(n)回文子串算法,其他的解法都是这种,只不过每个人都讲得比较混乱,唯有这个虽然也混乱,但是图画得比较清晰,我就借用了这篇文章的图了。

    请看下图:

    假设用一个数组p(长度为字符串长度,注意,在处理之前,为了使字符串长度的奇偶不影响处理过程,进行了插入“#”的预处理操作,一会看代码就明白了为什么这么处理了),p[i]表示以s[i]为中心的最长回文子串,在计算p[i]之时我们已知了p[0]….p[i-1],以及当前所有计算出来的最长回文子串所能延伸到的最右位置mx以及其对应的回文中心id(在代码里,我将它称为center),那么,i关于id的对称位置j=2*id-i, 且如果mx>i,必然有p[i]至少等于min(p[j],mx-i),如果mx<=i,那只有老老实实从p[i]=1计算了,这个大大减少了计算量。

    image

    image

    如果mx>i,那么mx之外的字符是没有经过比较的,所以p[i]应该不比mx-i大,为啥?分析如下,如果p[j]<mx-i,说明整个以j为中心的回文子串都在以id为中心的回文子串之内。那么直接取p[j]作为p[i]的值肯定没错,反之,说明,p[j]有一部分伸出,这部分得减掉。

    代码如下:

    class Solution {
    public:
        string longestPalindrome(string s) {
            // Start typing your C/C++ solution below
            // DO NOT write int main() function
            string s2;
            s2.push_back('#');
            for(int i=0;i<s.length();++i)
            {
                s2.push_back(s[i]);
                s2.push_back('#');
            }
            
            vector<int> p;
            p.assign(s2.length(),0);
            
            int mx=0;
            int center=0;
            
            int max=1;int loc=0;
            
            for(int i=0;i<s2.length();i++)
            {
                if(mx>i)
                {
                    p[i]=min(p[2*center-i],mx-i);
                }
                else p[i]=1;
                
                while((i-p[i])>=0&&(i+p[i])<s2.length())
                {
                    if(s2[i-p[i]]==s2[i+p[i]])p[i]+=1;
                    else break;
                }
                
                if((i+p[i]-1)>mx)
                {
                    mx=i+p[i]-1;center=i;
                }
                
                if(p[i]>max)
                {
                    max=p[i];
                    loc=i;
                }
            }
            
            string result;
            for(int i=loc-max+1;i<=loc+max-1;++i)
            {
                if(s2[i]!='#')result.push_back(s2[i]);
            }
            
            return result;
            
            
        }
    };
  • 相关阅读:
    当el-input输入多行内容,反显时,字符串需要换行显示
    【前端】记录自己在leetcode上的刷题之路
    本地提代码到github上,不显示贡献值的问题
    关于对象的深拷贝和浅拷贝
    js判断两个数值区间是否存在重叠或覆盖
    解决vue-print-nb打印el-table,不同分辨率下,打印显示不全的问题
    vue实现置顶功能
    el-table设置自定义表头,当表头内容过长时,鼠标悬浮显示完整内容
    省市用element级联选择器,构造树形结构的数据(两层)
    STL隐蔽知识点
  • 原文地址:https://www.cnblogs.com/obama/p/3268971.html
Copyright © 2011-2022 走看看