leetcode 5. Longest Palindromic Substring

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        lens=len(s)
        dp = [[0 for i in range(lens)]  for i in range(lens)]
        for i in range(0,lens):
            for j in range(0,lens):
                dp[i][j]=0
        for i in range(0,lens):
            dp[i][i]=1
        mx=0
        x=0
        y=0
        for j in range(1,lens):
            i=0
            while(i+j<lens):
                if s[i]==s[i+j] and i+1<lens and dp[i+1][i+j-1]!=-1:
                    dp[i][i+j]=dp[i+1][i+j-1]+2
                else:
                    dp[i][i+j]=-1
                if dp[i][i+j]>mx:
                    mx=dp[i][i+j]
                    x=i
                    y=i+j
                i=i+1
        ans=s[x:y+1]
        return ans

字符串处理的经典问题,可以使用动态规划的区间dp解决

这里使用python写了一个区间dp,基本思想是如果s[i+1:j+i]是一个回文串或空串的话,那么dp[i][j+i]=dp[i+1][j+i-1]+2

当然还有很多的方法比如

枚举法:n*n

枚举字符串的对称轴,用两个指针从中间向外拓展,遇到有相同的字符串时就停止

manacher:O(n)

首先在两个字符中间插入一个特殊字符,如同这样:# a # b # a #

然后每一个字符就相当于一个对称轴了,我们可以就此跑n*n的算法,但可以不满足于此

f[i] 表示以第i个字符为中心的最长回文子串的长度,枚举回文串的中心位置,统计使得回文串右边界(j + f(j) / 2)最大的那个j,然后再计算每一个i的时候,都可以通过f(i)≥min⁡{f(2*j-i), f(j)-2*(i-j)}这个公式来知道f(i)的一个最小值

简单的说,我们记录一个每次能访问到最远端点,然后枚举下一个中心结点时利用我们的公式推知那个最小值,每次就从那个最小值开始访问就行了

当然我们获得的长度最后还要减去特殊字符

示例代码:(来源于互联网)

其中p数组存的是中心结点最长回文串的半径

void pk()
 {
     int i;
     int mx = 0;
     int id;
     for(i=1; i<n; i++)
     {
         if( mx > i )
             p[i] = MIN( p[2*id-i], mx-i );        
         else
             p[i] = 1;
         for(; str[i+p[i]] == str[i-p[i]]; p[i]++)
             ;
         if( p[i] + i > mx )
         {
             mx = p[i] + i;
             id = i;
         }
     }
 }

当然还有一些复杂的数据结构AC自动机,后缀自动机这样的东西可以使用

不过更加好用的要算回文自动机了,相关链接:http://www.cnblogs.com/crazyacking/p/4742400.html

 

posted on 2017-04-05 17:22  此剑之势愈斩愈烈  阅读(92)  评论(0编辑  收藏  举报

导航