Leetcode---Longest Palindromic Substring

来源:互联网 发布:linux c代码创建目录 编辑:程序博客网 时间:2024/06/02 04:35

最长回文字串(Longest Palindromic Substring)

题目: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.

题目连接https://leetcode.com/problems/longest-palindromic-substring/

    大意是给定一个字符串S,求S中最长的回文字串,回文字符串是指从坐到右和从右到左都是一样的字符串,例如:“西湖回游鱼游回湖西”、“ABDCDBA”、“abccba”等等诸如此类的字符串,单个字符的串,也是回文串。

思路1:暴力解法,枚举S的所有字串,判断每个字符串是否是回文串,返回最长的串,当字符串很长的时候,枚举也只能想想了,更别说还要判断是否是回文。
思路2:枚举中心法,我们感兴趣的只是串中的回文字串,因为回文串的性质,那么我们可以枚举串中每一个字符,来检查以它为中心的串是不是回文串,并选取其中最长的返回。
     
     例如:ABDCDBA  
    1.以A为中心,A的左边没有字符,所以只能是A当作一个回文。
2.以B为中心,那么比较B的左边和右边字符是否相等。相等,是回文。否则,不是。
3.以此类推,直到所有的字符作为中心判断完。
假设以i为中心,j为i左右的长度,且满足条件1:(i-j)>=0 && (i+j)<S.size(); j从0开始,到不能满足条件1结            束,分别判断,判断完成以i为中心后,以i+1为中心再进行类似判断。当然还有一个问题,就是回文串的长度有          可能是奇数,也可能是偶数。例如ABA、ABBA都是回文。这个时候只需要对奇数还是偶数进行分别判断:
               奇数时:判断S[i-j] == S[i+j],j满足(i-j)>=0 && (i+j)<S.size()
       偶数使:判断S[i-j] == S[i+j+1],j满足(i-j)>=0 && (i+j+1)<S.size()
CODE: 
             

思路3:先看下面的例子:
     A  AABABBAABCBABC ....
      可以看出什么? A按规定是一个回文,要判断BAB是不是回文,那么判断B==B,且A是不是回文。判断BAAB,则判断B==B? 且AA是不是回文。以此类推,可以总结    到:
1.单个字符是回文。
2.两个字符相同是回文,否则不是。
3.长度大于等于3的串,满足s[0]==s[s.size-1] && s.substr(1,s.size-2)是不是回文。满足则是,否则不是。
   更一般化来讲:
对于以i为起点,j为长度的string是不是回文串,只需要判断,s[i]==s[s+j-1]且s[i+1 to i+j-2]之间的串是不是回文串,这样问题规模就减小了,对于规模    大的问题转换到小规模问题求解,那么很容易想到的就是动态规划。
    DP[i][i] = true;    i<s.size();
DP[i][i+1] = true;  if( s[i]==s[i+1] && i<s.size()-1)
DP[i][j] = true;    if( s[i]==s[j] && DP[i+1][j-1] && i<size & j < size)
   按照这个思路很自然可以得出代码:
   CODE
   

  抛开暴力枚举的方法,因为效率太低了,中心枚举和动态规划的时间复杂度都是O(n^2),还有没有更高效的方法呢?当然有,这就是传说中的Manacher算法,这个方法需要点想象力啊。

思路4:Manacher算法,这就是个传说。Manacher算法思想是来自上述“中心扩展法”,在“中心法”中要考虑回文串是奇数还是偶数,有没办法统一处理呢?有,这就是Manacher算法。
   该算法首先将字符串的每个字符之间加入一个特殊字符,并且在字符串开头加入一个标志来更好处理越界和编码问题。例如:s=“abba”编码后是:s=“$#a#b#b#a#”。
   然后,用一个数组p来记录每个字符是s[i]为中心的的回文串向左或向右的长度,则原字符串s的回文长度为max(p[i]-1)。因为对于一个回文字符串s加入特殊字符后,该回文串加上特殊字符后依然会是一个回文串,且编码后的回文串的长度为2*s.size+1。那么数组记录的最大值为s.size+1,比原回文的长度多1。故求取p[]的最大值减1就是原字符串中最大的回文串。
   现在最重要的问题就是怎么求解p[],这似乎又回到原来开始的问题了,非也。因为加了特殊字符,会出现一些有用的结论。
   假设现在求p[i]的值,则p[0]...p[i-1]的值已经求出,maxlen为目前已经求出的回文串延伸到右边的最大长度,id为p[0]到p[i-1]最大回文串的中心,j为i关于id的对称点,即j=2*id-i。那么:
   1.如果i不在maxlen范围内,即不在任何回文串中,则p[i]=1(本身为回文)。接着判断p[i+j]==p[i-j],为真则++p[i],否则2;
   2.p[i]>=min(p[2id-i],maxlen-i]。
   证明:
情况1:
        

情况2:
情况3:



0 0
原创粉丝点击