LintCode 最長迴文子串

給出一個字符串(假設長度最長爲1000),求出它的最長迴文子串,你可以假定只有一個滿足條件的最長迴文串。

樣例
給出字符串 “abcdzdcab”,它的最長迴文子串爲 “cdzdc”。

挑戰
O(n2) 時間複雜度的算法是可以接受的,如果你能用 O(n) 的算法那自然更好。

第一次AC的連O(n2)都不是的,是O(n3),遍歷所有子串。代碼如下:

class Solution:
    """
    @param: s: input string
    @return: the longest palindromic substring
    """
    def longestPalindrome(self, s):
        # write your code here
        n=len(s)
        result=""
        m=0
        for i in range(n):
            for j in range(n-1,i,-1):
                if s[j]==s[i]:
                    temp=s[i:j+1]
                    res=self.judge(temp)
                    if res>m:
                        result=temp
                        m=res
            if m<1:
                result=s[i]
        return result
    def judge(self,s):
        n=len(s)
        if n==0:
            return 
        for i in range(n/2):
            if s[i]!=s[n-1-i]:
                return -1
        return n

然後參考了曾會玩的文章,感謝。
O(n2)的算法。利用迴文串的對稱性,從中心向兩端擴展。對整個字符串來說,可能爲中心的包括n個字符,和n-1個間隙,分兩種情況來判斷。代碼如下:

class Solution:
    """
    @param: s: input string
    @return: the longest palindromic substring
    """
    def longestPalindrome(self, s):
        # write your code here
        n=len(s)
        result=""
        m=0
        for i in range(n):
            j=1
            temp=s[i]
            while(i-j>=0 and i+j<n ):
                if s[i-j]==s[i+j]:
                    temp=s[i-j]+temp+s[i+j]
                    j+=1
                else:
                    break
            print temp
            if len(temp)>m:
                m=len(temp)
                result=temp
        for i in range(1,n):
            j=1
            temp=""
            while(i-j>=0 and i+j-1<n):
                if s[i-j]==s[i+j-1]:
                    temp=s[i-j]+temp+s[i+j-1]
                    j+=1
                else:
                    break
            print temp
            if len(temp)>m:
                m=len(temp)
                result=temp
        return result

O(n)的算法,manacher算法。相當於對O(n2)算法的改進,O(n2)在判斷過程中重複判斷了相同的子串,效率較低。
具體解析可以參考曾會玩的文章,我覺得解釋的很棒,容易理解。需要注意的一點就是 迴文半徑和下標,處理起來要小心一點。代碼如下:

class Solution:

    """
    @param: s: input string
    @return: the longest palindromic substring
    """
    def longestPalindrome(self, s):
        # write your code here
        t=s
        s='#'+'#'.join(s)+'#'
        n=len(s)
        dp=[0]*n    #記錄迴文半徑
        right=0;    #當前所有迴文子串能達到的最右端字符下標
        pos=0;    #以right爲最右端的迴文子串的中心字符下標
        for i in range(n):
            if i>=right:
                dp[i]=1 
            else:
               if i+dp[pos-(i-pos)]<=right: #s[i]關於s[pos]對稱的s[pos-(i-pos)]的迴文半徑+i和right相比
                   dp[i]=dp[pos-(i-pos)]
               else:
                   dp[i]=right-i+1
            while(i+dp[i]<n and i-dp[i]>=0 and s[i+dp[i]]==s[i-dp[i]] ):
                dp[i]+=1
            if dp[i]>right:
                pos=i
                right=dp[i]
        return s[pos-(dp[pos]-1):pos+(dp[pos]-1)+1].replace('#','')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章