飘逸的python - 字符串的KMP匹配算法

首先我们来看一下字符串的朴素匹配.

可以想象成把文本串s固定住,模式串p从s最左边开始对齐,如果对齐的部分完全一样,则匹配成功,失败则将模式串p整体往右移1位,继续检查对齐部分,如此反复.

#朴素匹配
def naive_match(s, p):
    m = len(s); n = len(p)
    for i in range(m-n+1):#起始指针i
        if s[i:i+n] == p:
            return True
    return False

关于kmp算法,讲的最好的当属阮一峰的<字符串匹配的KMP算法>.一路读下来,豁然开朗.

其实就是,对模式串p进行预处理,得到前后缀的部分匹配表,使得我们可以借助已知信息,算出可以右移多少位.即 kmp = 朴素匹配 + 移动多位.

更多细节请看阮一峰的文章,这里就不展开了.

下面给出python的代码实现.

#KMP
def kmp_match(s, p):
    m = len(s); n = len(p)
    cur = 0#起始指针cur
    table = partial_table(p)
    while cur<=m-n:
        for i in range(n):
            if s[i+cur]!=p[i]:
                cur += max(i - table[i-1], 1)#有了部分匹配表,我们不只是单纯的1位1位往右移,可以一次移动多位
                break
        else:
            return True
    return False

#部分匹配表
def partial_table(p):
    '''partial_table("ABCDABD") -> [0, 0, 0, 0, 1, 2, 0]'''
    prefix = set()
    postfix = set()
    ret = [0]
    for i in range(1,len(p)):
        prefix.add(p[:i])
        postfix = {p[j:i+1] for j in range(1,i+1)}
        ret.append(len((prefix&postfix or {''}).pop()))
    return ret

print naive_match("BBC ABCDAB ABCDABCDABDE", "ABCDABD")
print partial_table("ABCDABD")
print kmp_match("BBC ABCDAB ABCDABCDABDE", "ABCDABD")
时间: 2024-08-03 15:53:07

飘逸的python - 字符串的KMP匹配算法的相关文章

KMP匹配算法

KMP算法可以在O(n+m)的时间数量上完成串的模式匹配操作. n指的是主字符串的长度,m指的是模式字符串的长度. 求next数组的算法: void get_next(char T[], int next[]) { i = 1; next[1] = 0; j = 0; while( i <= T[0]) { if(j == 0 || T[i] == T[j]) { ++i; ++j; next[i] = j; } else j = next[j]; } } KMP匹配算法: int KMP(ch

字符串查找与匹配算法

一.字符串查找:1.在Word. IntelliJ IDEA.Codeblocks等编辑器中都有字符串查找功能.2.字符串查找算法是一种搜索算法,目的是在一个长的字符串中找出是否包含某个子字符串. 二.字符串匹配:1.一个字符串是一个定义在有限字母表上的字符序列.例如,ATCTAGAGA是字母表 E ={A,C,G,T}上的一个字符串.2.字符串匹配算法就是在一个大的字符串T中搜索某个字符串P的所有出现位置.其中,T称为文本,P称为模式,T和P都定义在同一个字母表E上.3.字符串匹配的应用包括信

字符串的KMP算法替换

1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 6 7 class myString 8 { 9 private: 10 string mainstr; 11 int size; 12 void GetNext(string p,int next[]); 13 int KMPFind(string p,int next[]); 14 public: 15 myString(); 16 //~myS

python学习笔记:python字符串

二.python字符串操作符 1. 对象标准类型操作符 Python对象的标准类型操作符一共就三种:对象值的比较.对象身份的比较.布尔类型.其中对象值的比较主要是大于.小于.不等于等的数学比较符:对象身份的比较主要是is和is not这两个符号:布尔类型主要是not.and.or等的逻辑运算符. 字符串标准类型操作符也是这些,在做比较操作的时候,字符串是按照ASCII值的大小来比较的. 2. 序列类型操作符 切片操作符 主要分为三种,分别是正向索引.反向索引.默认索引.下图中显示索引的编号: 注

飘逸的python - __new__、__init__、__call__傻傻分不清

__new__: 对象的创建,是一个静态方法.第一个參数是cls.(想想也是,不可能是self,对象还没创建,哪来的self) __init__ : 对象的初始化, 是一个实例方法,第一个參数是self. __call__ : 对象可call.注意不是类,是对象. 先有创建,才有初始化.即先__new__,而后__init__. 上面说的不好理解,看样例. 对于__new__ class Bar(object): pass class Foo(object): def __new__(cls,

Python 字符串操作方法大全

python字符串操作实方法大合集,包括了几乎所有常用的python字符串操作,如字符串的替换.删除.截取.复制.连接.比较.查找.分割等,需要的朋友可以参考下. 1.去空格及特殊符号 s.strip().lstrip().rstrip(',') 2.复制字符串 #strcpy(sStr1,sStr2) sStr1 = 'strcpy' sStr2 = sStr1 sStr1 = 'strcpy2' print sStr2 3.连接字符串 #strcat(sStr1,sStr2) sStr1 =

Python 字符串前面加&#39;r&#39;

python中r的用法,r'str'表示raw string,既忽略转义字符.因为和windows不一样,python中认为\就是转义字符escape sequences的标志. 在python2.x中,unicode字符串需要在字符串前加u来表示,比如 str=u'汉字' 而在python3.x中,unicode字符串已经是默认格式,因此不再需要加u, 如果你加了u,会报语法错误: str=u'汉字' SyntaxError: invalid syntax Python 字符串前面加'r'

Python字符串操作

isalnum()判断是否都是有效字符串 ? 1 2 3 4 5 6 7 8 9 10 11 12 >>> ev1 = 'evilxr' >>> ev2 = 'ev1il2xr3' >>> ev3 = '.,/[email protected]#' >>> a = ev1.isalnum() >>> print a True >>> b = ev2.isalnum() >>> pr

【代码学习】PYTHON字符串的常见操作

一.字符串运算符 下表实例变量 a 值为字符串 "Hello",b 变量值为 "Python": 操作符 描述 实例 + 字符串连接 >>>a + b 'HelloPython' * 重复输出字符串 >>>a * 2 'HelloHello' [] 通过索引获取字符串中字符 >>>a[1] 'e' [ : ] 截取字符串中的一部分 >>>a[1:4] 'ell' in 成员运算符 - 如果字符串