• 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;
            
            
        }
    };
  • 相关阅读:
    云服务器迁移的那些事之一
    《编译原理》(第二版)第一章的学习笔记(一)
    vs 实用扩展
    SQL多的是,你不知道的事
    Entity Framework 批量插入 提速
    oracle 回收已删除的表
    发现一个奇怪的问题!
    看到易办网的希望...
    asp.net不认为数据库字段的空值为null
    什么是伪url?
  • 原文地址:https://www.cnblogs.com/obama/p/3268971.html
Copyright © 2020-2023  润新知