20240728----kmp算法和海明码算法

(一)KMP算法

1.KMP定义:

字符串匹配算法,在文本中寻找一个给定的模式(子串)。KMP算法通过预处理模式字符串,使得在匹配过程中可以跳过不必要的字符,从而提高匹配效率。

KMP算法图参考博客1
KMP算法参考博客2
KMP算法参考博客3
2.部分匹配表Next:对于字符串str,从 第一个字符开始的每个子串 的 最后一个字符 与 该子串的最长公共前后缀的长度 的对应关系表格。这个表我们以 int[] next 数组方式进行存储。

📝 再比如说一个字符串 str = “ABCABD”
• 对于str从索引为0开始的子串 “A” 而言:
a. 前缀:不包含最后一个字符A的 所有以第一个字符A开头 的 连续子串 不存在
b. 后缀:不包含第一个字符A 的 所有以最后一个字符A结尾 的 连续子串 不存在
• 因此该子串的最长公共前后缀 为 0
• 对于str从 索引为0 开始的子串 “AB” 而言:
a. 前缀:不包含 最后一个字符B 的 所有以第一个字符A开头 的 连续子串 有 —— “A”
b. 后缀:不包含 第一个字符A 的 所有以最后一个字符B结尾 的 连续子串 有 —— “B”
• 因此该子串的最长公共前后缀 为 0
• 对于str从 索引为0 开始的子串 “ABC” 而言:
a. 前缀:不包含 最后一个字符C 的 所有以第一个字符A开头 的 连续子串 有 —— “A”,“AB”
b. 后缀:不包含 第一个字符A 的 所有以最后一个字符C 结尾 的 连续子串有 —— “BC”,“C”
• 前缀与后缀的连续子串不存在相同的,因此该子串的最长公共前后缀 为 0
• 对于str从 索引为0 开始的子串 “ABCA” 而言:
a. 前缀:不包含 最后一个字符A 的 所有以第一个字符A开头 的 连续子串 有 —— “A”,“AB”,“ABC”
b. 后缀:不包含 第一个字符A 的 所有以最后一个字符A 结尾 的 连续子串有 —— “BCA”,“CA”,“A”
• 前缀与后缀的连续子串中存在相同且最长的子串 A,因此该子串的最长公共前后缀 为 1
• 对于str从 索引为0 开始的子串 “ABCAB” 而言:
a. 前缀:不包含 最后一个字符B 的 所有以第一个字符A开头 的 连续子串 有 —— “A”,“AB”,“ABC”,“ABCA”
b. 后缀:不包含 第一个字符A 的 所有以最后一个字符B 结尾 的 连续子串有 —— “BCAB”,“CAB”,“AB”,“B”
• 前缀与后缀的连续子串中存在相同且最长的子串 AB,因此该子串的最长公共前后缀 为 2
• 对于str从 索引为0 开始的子串 “ABCABD” 而言:
a. 前缀:不包含 最后一个字符D 的 所有以第一个字符A开头 的 连续子串 有 —— “A”,“AB”,“ABC”,“ABCA”,“ABCAB”
b. 后缀:不包含 第一个字符A 的 所有以最后一个字符D 结尾 的 连续子串有 —— “BCABD”,“CABD”,“ABD”,“BD”,“D”
• 前缀与后缀的连续子串不存在相同的,因此该子串的最长公共前后缀 为 0

(前后缀的书写顺序是从左往右书写)。
• 子串 “A”:最后一个字符是 A,该子串的最长公共前后缀长度是 0,因此对应关系就是 A - 0
• 子串 “AB”:最后一个字符是 B,该子串的最长公共前后缀长度是 0,因此对应关系就是 B - 0
• 子串 “ABC”:最后一个字符是 C,该子串的最长公共前后缀长度是 0,因此对应关系就是 C - 0
• 子串 “ABCA”:最后一个字符是 A,该子串的最长公共前后缀长度是 1,因此对应关系就是 A - 1
• 子串 “ABCAB”:最后一个字符是 B,该子串的最长公共前后缀长度是 2,因此对应关系就是 B - 2
• 子串 “ABCABD”:最后一个字符是 D,该子串的最长公共前后缀长度是 0,因此对应关系就是 D - 0
因此综上,我们说该字符串 str 的部分匹配表为:
在这里插入图片描述

2.KMP算法自己的理解:

(1)按照暴力匹配的算法:母串(文本字符串)保持不变,字串进行匹配。若每次与母串(文本字符串)不匹配,子串向后移动一位,一直循环直到比较的主串的剩余长度小于模式串的长度。
(2)KMP算法的大致步骤

  1. 求出模式字符串patternStr的部分匹配表,已知待匹配的字符串 matchStr
  2. 定义两个指针 i 和 j,分别指向 patternStr 和 matchStr ,初始化为0
  3. 判断 patternStr[i] 和 matchStr[j] 是否相等
    • 如果相等,则继续向后匹配:i++, j++
    • 如果不相等,则 i 不变,调整 j 为 模式字符串pattern 的 上一个子串(索引 [ 0, j-1 ])的最长公共前缀字符串的下一个索引位置,该索引位置也是最长公共前缀/后缀字符串的长度:j = next[ j - 1 ]
    (3)假设主串S匹配到j的位置,模式串P匹配到i的位置,还没匹配结束,继续匹配下去会出现下面两种情况:

1,当P[i] == S[j]时,则继续匹配 i++,j++;
2,当P[i] != S[j]时,则 i =next[i],j++,此时等价于模式串P向右移动了 i -next[i]个单位;
比如现在i=5,最长公共前后缀的next[5].所以字串(模式串)向右移动了5-next[5].

(二)海明码算法

海明码参考博客1
m表示数据位的位数,k表示海明校验码的位数
在这里插入图片描述
发送端:

设要传输的数据为101101100

(1)可知m=9,由公式,可知k最小值为4,所以总共要传输的数据位数为9+4=13;

(2)海明校验码放在索引号为2^n的位(n=0,1,2,…,k-1)上,本例中k=4,所以校验位的索引为第1,2,4,8位,于是在下表中把这几位空出来.
在这里插入图片描述
在这里插入图片描述
备注:由(3)得从右往左数,分别是H1(右数第一列是1的索引号),H2(右数第2列是1的索引号),H4(右数第3列是1的索引号),H8(右数第4列是1的索引号)为校验位.
然后根据索引号去(2)中找到索引号对应的符号。把这些符号进行异或处理。

具体步骤如下:

上表中,先说每一行的内容:从第二行开始,每一行的第一列代表索引号,这个索引号是除去了海明校验位之外的其他所有位。后面几列为该索引号对应的二进制表示,其位数取决于第(1)步计算得出的海明校验码的位数,比如第二行,索引号是3,十进制3对应的二进制就是0011,之所以用4位表示是因为这段信息码需要4个海明校验位。

再看列信息:第一行最右边数字1所对应的列里,出现1的,就表示可以用第H1位完成校验,出现数字0则表示不能用H1位进行校验,因此,由上表可知:

校验位H1负责校验:第3,5,7,9,11,13位(上表黄色高亮显示部分),对应位置上的值进行异或得:1⊕0⊕1⊕0⊕1⊕0=1,由于海明校验做的是偶校验,则H1=1;

校验位H2负责校验:第3,6,7,10,11位(上表蓝色高亮显示部分),对应位置上的值进行异或得:1⊕1⊕1⊕1⊕1=1;
校验位H4负责校验:第5,6,7,12,13位,对应位置上的值进行异或得:0⊕1⊕1⊕0⊕0=0;
校验位H8负责校验:第9,10,11,12,13位,对应位置上的值进行异或得:0⊕1⊕1⊕0⊕0=0。

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值