对于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算法。