母串匹配子串的常用算法,定义Tag为主串,Ptn为子串(模式串),如果在主串Tag的第pos个位置后存在与子串Ptn相同的子串,返回它在主串Tag中第pos个字符后第一次出现的位置,否则返回-1。BF算法为暴力回溯求解算法,KMP算法相对优化。
BF算法
思路
定义两个索引值i和j分别为Tag和Ptn的带匹配字符,匹配则自增,不匹配则i回溯为i-j+1,j回溯为0,当二者有其一索引至尾端则跳出循环,若跳出循环后j索引完了Ptn则返回i-length(Ptn),否则返回-1。
代码
1 | /* |
验证
1 | int main() |
KMP算法
思路
- 回溯的方法不同,一旦失配,i不回溯,j回溯到一个特殊的位置,采用next[length(Ptn)]记录元素失配后回溯到的下一位置。
- 关键在与next数组的求解,下面举例。key:next数组是针对子串的,和母串没关。
next数组理解的举例
- 对于子串“ABCDABD”,对应的next数组为“-1 0 0 0 0 1 2”,下面解释next数组怎么来的。
- 当匹配到第六位的“B”时,如果发生了失配,j将回到1即第二位开始配,因为失配位的前一位是A,而A在子串的最开头出现过,所以j没必要回溯到0再开始匹配了。
- 当匹配到第七位的“D”时,如果发生了失配,j将回到2即第三位开始配,因为失配位的前两位是AB,而AB在子串的最开头出现过,所以j没必要回溯到0再开始匹配了,直接从第三位开始匹配。
- 所以next数组记录的是,当前位置元素往前看,比如D往前看,出现的连续字符满足和从头开始数连续字符相等的数量。比如从D往前看为AB,所以D对应2。
代码
1 | /* |
验证
1 | int main() |