先声明,本人菜鸟一个,写博客是为了记录学习的过程,以及自己的理解和心得,可能有的地方写的不好,希望大神指出。。。

抛出问题

  给定一个文本串test_str(被匹配的字符串)和模式串pat_str(需要从文本串中匹配的字符串),从文本串test_str中找出模式串pat_str第一次出现的位置,没有的话返回 -1

暴力方式

  在说kmp之前,我们先来讲下“暴力方式“,也就是说我们最原始的方法。

  

text_str = 'asdabcdace'
pat_str = 'abcdace' def str_match(text_str,pat_str):
for i in range(0,len(text_str)):
j = 1
while j < len(pat_str):
if text_str[i:i+j] != pat_str[0:j]: #从text_str第i个字符开始,看匹配是否成功
break #匹配失败,直接跳出循环,i+1,继续从第一个字符匹配
j += 1 #匹配成功就继续匹配下一个字符,知道pat_str每个字符都匹配完
if j == len(pat_str):
return i
return -1 print(str_match(text_str,pat_str))

  之所以称之为暴力解法,就是因为每次匹配失败之后就将模式串,向后移动一位,从头开始匹配,一直循环下去。造成时间复杂度高,kmp也就是优化这个地方,每一次匹配失败,下次移动的距离next值

KMP

  如果让我完全给你讲懂kmp算法可能不太容易,我只能大致粗略的将下它的一步步实现。我认为就一个重点,

  如何求出模式串每个字符对应的next值

    因为可能,每一次匹配失败的长度的字符不一样,也就对应每次移动的距离不一样,那我们如何求每个字符对应的next值,这就引出了另一个概念

    最大前缀最大后缀

    

  假定最大前缀=最大后缀,长度为k 那么第i位字符,对应的next值就为k+1,一次循环就能求出每个字符的next值

代码实现

  

#求字符串的next值
text_str = 'asdabcdace'
pat_str = 'abcdace' #得到字符对应的next值
def str_next(s):
#前两个字符默认等于1
next = [1,1]
for x in range(2,len(s)):
next.append(str_max_prx(s,x,next[x-1]-1) + 1)
return next
#参数 s字符串,匹配进行到的位置,下次开始匹配的位置
def str_max_prx(s,x,last_value):
next = 0
for i in range(last_value,x):
if s[0:i] == s[x-i:x]:
next = i
return next
def str_match(s,m):
next = str_next(s)
i=0
s_len = len(s)
m_len = len(m)
while i <= m_len:
flag = True #标志位,用来判断是否匹配成功
index = 1
while index <= s_len:
if m[i:i + index] != s[0:index]:
i = i + next[index]
flag = False
break
else:
index += 1
if flag:
break
if i >= m_len:
i = -1
return i
res = str_match(pat_str,text_str)
print(res)

  代码就是这样,很多东西可能还需要自己理解。我记个笔记,为之后方便查找,希望对你能有帮助。

python3 kmp 字符串匹配的更多相关文章

  1. {Reship}{KMP字符串匹配}

    关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827

  2. 洛谷P3375 - 【模板】KMP字符串匹配

    原题链接 Description 模板题啦~ Code //[模板]KMP字符串匹配 #include <cstdio> #include <cstring> int cons ...

  3. Luogu 3375 【模板】KMP字符串匹配(KMP算法)

    Luogu 3375 [模板]KMP字符串匹配(KMP算法) Description 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来 ...

  4. 洛谷P3375 [模板]KMP字符串匹配

    To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...

  5. P3375 【模板】KMP字符串匹配

    P3375 [模板]KMP字符串匹配 https://www.luogu.org/problemnew/show/P3375 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在 ...

  6. 洛谷—— P3375 【模板】KMP字符串匹配

    P3375 [模板]KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如 ...

  7. P3375 模板 KMP字符串匹配

    P3375 [模板]KMP字符串匹配 来一道模板题,直接上代码. #include <bits/stdc++.h> using namespace std; typedef long lo ...

  8. KMP字符串匹配 模板 洛谷 P3375

    KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...

  9. KMP字符串匹配学习

    KMP字符串匹配学习 牛逼啊 SYC大佬的博客

随机推荐

  1. unity 中的UGUI 屏蔽鼠标穿透

    void Update() { if(IsTouchedUI()) { Debug.Log("当前触摸在UI上"); } else { Debug.Log("当前没有触摸 ...

  2. Mac High Sierra 降级安装Mac Sierra

    1>.将你装备好的U盘用Mac自带的磁盘管理工具格式化成Mac OS扩展(日志式),名称输入disk:2>.打开终端工具,按以下步骤操作:(均不含引号,如未设置系统密码,请前往设置> ...

  3. [Leetcode 90]求含有重复数的子集 Subset II

    [题目] Given a collection of integers that might contain duplicates, nums, return all possible subsets ...

  4. python笔记17-全局变量、局部变量

    在函数里面定义变量叫局部变量,它只能在函数里面用出了该函数外,就不能使用了在函数外面定义的变量,是全局变量,在函数内也可以使用 如果想在函数里面修改全局变量的值,那么要先用global关键字声明 要修 ...

  5. be动词的形式和用法

    Be动词的形式: be, is, am, are, was, were, being, been 1.The man is back 2.They are back 3.He was back 4.T ...

  6. 远程链接 aws Windows Server 2016 Base Nano

    第一次接触Windows Server 2016 Base Nano,平时工作中或者自己私下使用win的服务器都是带桌面版本的 而这次在aws一不小心开了一台Nano服务,刚开始我都不知道这个是什么玩 ...

  7. Django runserver UnicodeDecodeError

    编码问题可以说是我遇到过的python 2.7最大的败笔 今天写django时,很简单的一个项目却报UnicodeDecodeError,而我的代码中一个中文字符都没有出现. 如下: 网上找到的所谓解 ...

  8. mysql中外键的创建与删除

    外键的创建 方法1:创建表的时候设置(外键名随机生成) 1.前提条件,必须要有一个主表,这里设为persons 2.主表中必须设置主键字段primary key,这里设为id_p //创建数据库dat ...

  9. mysql数据库的基本操作命令整理

    快捷键 ctrl+l 清屏 ctrl +a 回到行首 ctrl + e 回到行末   数据库操作 进入数据库 方式1 mysql -u用户名 -p 密码 --------直接输入密码,缺点,会暴露自己 ...

  10. vim分屏操作

    启动分屏 1.使用大写O参数进行垂直分屏 $ vim -On file1 file2 ... 2.使用小写o参数进行水平分屏 $ vim -on file1 file2 ... 注: n是数字,表示分 ...