字符串匹配(KMP算法)

  1. 背景:
    上课的时候,老师讲:这种题目要用KMP算法,当时我心里就想,我又不是傻子,鬼才用呢,那么麻烦,还要求next[]数组…最近做了几个题目,才发现,真香 哈哈,现在想想,我以前是脑子进水了吧?干嘛不用KMP呢…
    (在比较正规的比赛里面,如果不用KMP,你将会看到"Time Limit Exceeded")

2.大大怪将军:“废话不多说,来人,上题目。”
小小怪下士:“报告将军,没找到题目。。。。。。。”
大大怪将军:“不管了,开炮!开炮!。。。。。。。”

首先,让我们先求出一个next[]数组,不要问我这个数组是干嘛的,因为。。。。。你懂得,呵呵呵

	next[0]=-1;
    int k=-1,j=0;
    while(j<s.length()-1){
        if(k==-1||s[k]==s[j])
            next[++j]=++k;
        else
            k=next[k];
    }

你肯定会这么想,“我靠,这么短,这是盗版的吧。。。。别慌,这确实是正版的,由于水平有限,我只能写一点注释”

就拿这串字符串来讲:“abcdabc”这串字符串得到的next[]是“-1 0 0 0 0 1 2”这串数字就是你今后,在哪里失配,需要跳转的位置。。。。这个字符串是这样的“abc”“d”“abc”组成的,(别问为什么,因为我是故意的)当你在第2个“abc”里面的c位置失配时,这是next[]里面对应的是2,下次移动的时候,你就可以直接跑到第一组“abc”的c那个位置继续匹配(怎么感觉像是打王者荣耀排位。。。)

相信你看完我这段话,肯定还是不理解,(估计心里骂我一千遍了)所以。。。。
来人,传送门:别点我
在这里插入图片描述
别谢我,我容易飘。。。嘿嘿嘿

### KMP字符串匹配算法的实现与原理 #### 原理概述 KMP算法的核心在于两个方面:部分匹配表(通常称为`next`数组)的构建以及如何利用这个表格来高效地完成字符串匹配[^1]。 #### 部分匹配(next数组)的作用及其计算方式 为了提高查找效率,KMP引入了前缀函数的概念,即对于模式串P中的每一个位置i,next[i]代表的是从起始至第i位子串的最大相同真前缀和真后缀长度。当遇到不匹配情况时,可以根据此信息决定跳转到哪个位置继续尝试而不是盲目移动指针回到起点重新开始比较。具体来说,在初始化阶段就要先算好整个模式串对应的next值列表作为后续操作的基础依据[^3]。 #### 匹配流程描述 实际执行过程中,主串S和模式串P各自设有一个游标变量指向当前考察字符处。每当两者对应项一致,则同步前进一位;反之如果发现差异存在但又不是首次访问该节点的话(意味着已经有过至少一轮成功的局部对比),那么就依照预先准备好的next映射关系调整后者所指示的位置直至找到新的候选点或者确认完全失败为止。值得注意的是在整个扫描期间内针对源数据流里的任一成员都只会被检验过一次而已,因此整体性能得以保持在线性级别上运行[^5]。 ```python def compute_next(pattern): m = len(pattern) next_array = [-1] * m k = -1 for q in range(1, m): while k >= 0 and pattern[k + 1] != pattern[q]: k = next_array[k] if pattern[k + 1] == pattern[q]: k += 1 next_array[q] = k return next_array def kmp_search(text, pattern): n, m = len(text), len(pattern) if not text or not pattern or n < m: return -1 next_array = compute_next(pattern) i = j = 0 while i < n: if j == -1 or text[i] == pattern[j]: i += 1 j += 1 if j == m: return i - j else: j = next_array[j] return -1 if j != m else (i - j) if __name__ == "__main__": txt = "ABCDABC" pat = "BCD" index = kmp_search(txt, pat) print(f"Pattern found at index {index}" if index != -1 else "No match found.") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值