python字符串以及他的匹配算法

對於python字符串的實現來說,它本身是一個線性表,根據前面我們講過的關於線性表的主體,我們可以實現一個字符串對象,在這裏我們需要說明的是,python字符串是一個不可變的對象,而且它的實現是一個一體式的順序表的實現(概念見前面文章)
所以,對於一個字符串的對象,它除了有字符存儲空間外還有字符串長度和一些配置信息的空間。(注意一點:python沒有字符對象,單個字符也認爲是一個字符串對象)
所以對於字符串的長度len函數和按下標取值複雜度都是O(1),但是其他的操作,如字符串的複製,切片等,都是O(n)。
再講一下字符串的複製(切片)的過程,這些過程都會建立一個新的字符串,python首先會計算出所需要存儲空間的大小,然後一個個的計算出要存儲再空間裏的字符串。這是python字符串複製(切片)的一個過程。

對於字符串中子串的查找,是一個高深的問題,當前的算法實現中經典的有兩種,一種是樸素匹配算法,一種是無回溯的KMP算法。

接下來我們將樸素的匹配算法。
過程是:
目標字符串t, 模式字符串p。
將p中的字符依次跟t中的比較,如果有一個不匹配,將t字符移到下一位, 再講p中的字符一個個的匹配,知道返回t中與p匹配的字符串。
這裏有兩種實現方法,一種返回第一個匹配的子串,另一種返回左右匹配子串的首字符的位置。實現如下:

#第一種
def naive_matching(t, p):
    # 這種找出第一個子串匹配的位置
    m, n = len(p), len(t)
    i, j = 0, 0
    while i < m and j < n:
        if p[i] == t[j]:
            i, j = i + 1, j + 1
        else:
            i, j = 0, j-i+1
    if i == m:
        return j -i
    return -1

print(naive_matching('fwekfwe', 'we'))
>>> 1

第二種

def naive_matching(t, p):
    list = []
    # 用於存儲匹配子串的首字符位置
    for i in range(len(t)):
        x, z, times = i, 0, len(p)
        if p[z] == t[i]:
            while times > 1:
                z += 1
                x += 1
                if p[z] != t[x]:
                    break
                times -= 1
            else:
            # 當while/for循環正常退出時纔會執行相應的else語句塊
                list.append(i)
    return list
# 這種匹配可以找出所有匹配子串的位置

print(naive_matching('rewwwtrtwewrfrwe', 'ww'))
>>> [2, 3]

這兩種實現方法的複雜度相對而言都比較高(有回溯),下一篇我們會將什麼是回溯和無回溯的KMP算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章