Python實現求最長子串長度

來源:互聯網
上載者:User

Python實現求最長子串長度

給定一個字串,求它最長的迴文子串長度,例如輸入字串'35534321',它的最長迴文子串是'3553',所以返回4。

最容易想到的辦法是枚舉出所有的子串,然後一一判斷是否為迴文串,返回最長的迴文子串長度。不用我說,枚舉實現的耗時是我們無法忍受的。那麼有沒有高效尋找迴文子串的方法呢?答案當然是肯定的,那就是中心擴充法,選擇一個元素作為中心,然後向外發散的尋找以該元素為圓心的最大迴文子串。但是又出現了新的問題,迴文子串的長度即可能是基數,也可能好是偶數,對於長度為偶數的迴文子串來說是不存在中心元素的。那是否有一種辦法能將奇偶長度的子串歸為一類,統一使用中心擴充法呢?它就是manacher演算法,在原字串中插入特殊字元,例如插入#後原字串變成'#3#5#5#3#4#3#2#1#'。現在我們對新字串使用中心擴充發即可,中心擴充法得到的半徑就是子串的長度。

現在實現思路已經明確了,先轉化字串'35534321'  ---->  '#3#5#5#3#4#3#2#1#',然後求出以每個元素為中心的最長迴文子串的長度。以下給出Python實現:

#!/usr/bin/python
# -*- coding: utf-8 -*-

def max_substr(string):
    s_list = [s for s in string]
    string = '#' + '#'.join(s_list) + '#'
    max_length = 0
    length = len(string)
    for index in range(0, length):
        r_length = get_length(string, index)
        if max_length < r_length:
            max_length = r_length
    return max_length

def get_length(string, index):
    # 迴圈求出index為中心的最長迴文字串
    length = 0
    r_ = len(string)
    for i in range(1,index+1):
        if index+i < r_ and string[index-i] == string[index+i]:
            length += 1
        else:
            break
    return length

if __name__ == "__main__":
    result = max_substr("35534321")
    print result

功能已經實現了,經過測試也沒有bug,但是我們靜下心來想一想,目前的解法是否還有最佳化空間呢?根據目前的解法,我們求出了‘35534321‘中每個元素中心的最大迴文子串。當遍曆到'4'時,我們已經知道目前最長的迴文子串的長度max_length是4,這是我們求出了以4為中心的最長迴文子串長度是3,它比max_length要小,所以我們不更新max_length。換句話說,我們計算以4為中心的最長迴文字串長度是做了無用功。這就是我們要最佳化的地方,既然某個元素的最長的迴文子串長度並沒有超過max_length,我們就沒有必要計算它的最長迴文子串,在遍曆一個新的元素時,我們要優先判斷以它為中心的迴文子串的長度是否能超越max_length,如果不能超過,就繼續遍曆下一個元素。以下是最佳化後的實現:

#!/usr/bin/python
# -*- coding: utf-8 -*-

def max_substr(string):
    s_list = [s for s in string]
    string = '#' + '#'.join(s_list) + '#'
    max_length = 0
    length = len(string)
    for index in range(0, length):
        r_length = get_length2(string, index, max_length)
        if max_length < r_length:
            max_length = r_length
    return max_length

def get_length2(string, index, max_length):
    # 基於已知的最長字串求最長字串
    # 1.中心+最大半徑超出字串範圍, return
    r_ = len(string)
    if index + max_length > r_:
        return max_length

    # 2.無法超越最大半徑, return
    l_string = string[index - max_length + 1 : index + 1]
    r_string = string[index : index + max_length]
    if l_string != r_string[::-1]:
        return max_length

    # 3.計算新的最大半徑
    result = max_length
    for i in range(max_length, r_):
        if index-i >= 0 and index+i < r_ and string[index-i] == string[index+i]:
            result += 1
        else:
            break
    return result - 1

if __name__ == "__main__":
    result = max_substr("35534321")
    print result

那麼速度到底提升了多少呢,以字串1000個‘1’為例,最佳化前的演算法執行時間為0.239018201828,最佳化後為0.0180191993713,速度提升了10倍左右

/usr/bin/python /Users/hakuippei/PycharmProjects/untitled/the_method_of_programming.py
0.239018201828
0.0180191993713

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.