【数据结构】串、KMP 算法 Python 版

一、

串就是字符串,本质上就是线性结构,其中可以存放各种字符,是线性表的一个具体表现形式。

二、 串表示法

串的表示方法主要有顺序存储,包括预定长度的串(定长顺序表示)和可变长度的串(堆分配存储);还有链表表示方法,包括存储结点大小为1的表示,还有每一个链表结点存储k个字符的链表表示。

链表表示法中,如果每一个结点存放一个字符的话,存储密度比较低,但是运算操作效率比较高;反之,每个节点都存储k个字符的话,操作起来会费劲一些,但是存储密度足够好。

三、 串的操作
对串的操作和对链表的操作差不多,唯一的区别就是如果每个节点中存放了K个字符的话,就需要考虑不被k整除的串索引的情况了。

主流语言中都有内置的串操作函数,这里也没必要再实现一遍串的数据结构了。但是串操作有一个和线性表很不同的就是串的模式匹配,更复杂的情况也就是正则表达式。

正常的串模式匹配算法就是在主串中以此匹配模式串,如果匹配成功,则返回首个字符的串索引,如果匹配失败,就继续匹配下一个字符。但是这种最基本的方法效率并不高,时间复杂度 o(m* n),两个参数分别代表字符串的长度和模式串的长度,空间复杂度o(1),这里没有考虑存放匹配的索引列表。
KMP算法是在此基础上的一种改进,它利用m维数组或其他线性结构存放了下一次匹配的模式位置,所以利用空间换取了一部分时间优化,但是具体时间复杂度会根据具体的字符串有较大的差别,但是性能如果最恶劣的话,也是o(m*n)。但是在很多时候,普通算法的执行时间并不比KMP慢多少,而且空间复杂度很低,所以现在依然被采用。

这里先略去正则表达式里复杂的语法规则不管,用Python实现一个普通搜索算法,然后再写一个最简单的KMP算法。

def pattern_match(str, pattern):  # 普通模式匹配算法,返回所有的索引
    index = []
    for _ in xrange(0, len(str)):
        i = _
        j = 0
        while j < len(pattern):
            if i < len(str) and str[i] == pattern[j]:
                i += 1
                j += 1
            else:
                break
        if j == len(pattern):
            index.append(_)
    return index

str = '90hnfuewdiohnfge'
pattern = 'hnf'
index = pattern_match(str, pattern)

print index

下面是 KMP算法,我自己写的:

def kmp_pattern_match(str, pattern):
    index = []
    j = 0
    for i in xrange(0, len(str)):
        j = get_next(pattern, j)
        while j < len(pattern):
            if i < len(str) and str[i] == pattern[j]:
                i += 1
                j += 1
            else:
                break
        if j == len(pattern):
            index.append(i-j)
            j = 0
    return index


def get_next(pattern, index):  # index 范围为 1 到 len(pattern),算上 len(pattern)
    next_list = next_index(pattern)
    return next_list[index]


def next_index(pattern):  # 返回一个列表,表示对应索引的下一跳索引
    next_list = [0, 0]
    for _ in xrange(2, len(pattern)):
        temp_list = [0]
        for i in xrange(1, _):
            if pattern[0:i] == pattern[_-i:_]:
                temp_list.append(i)
        next_list.append(max(temp_list))
    return next_list

在KMP上进一步扩展就是RE,正则表达式。但是记忆正则匹配是个麻烦的事情,前一段时间使用正则表达式处理文本比较多,所以很多字符的含义都记得,但是现在过了一段时间没有使用,很多的正则语法又忘记了。如果要自己实现一个正则表达式的话,我认为需要解决的几个问题是:栈队列存放模式,把模式和函数组合起来,模式匹配算法。

你可能感兴趣的:(Python,数据结构,算法)