一、模式匹配(Pattern Matching)简介
模式匹配是数据结构中字符串的一种基本操作,它用于在一条字符串中寻找与另一条子串相同的所有子串。
例如
在"hjh123abc"中寻找"hjh"
二、简单模式匹配
暴力匹配
int Index(String S,String T){
int i=1,j=1;
while(i<=S.length && j<=T.length){
if(S.ch[i] == T.ch[j]){
++i;
++j;
}
else{
i = i - j + 2;
j = 1;
}
}
if(j > T.length) return i-T.length;
else return 0;
}
思想:用计数指针i
和j
分别指示主串和子串待比较字符位置。
- 从主串第一个字符开始,使用模式串进行匹配
- 相等则接着检查后续字符,不相等,则模式串的
j
返回第一个字符,主串从下个字符开始接着比较
最坏时间复杂度: O ( n m ) O(nm) O(nm)
n
和m
分别为主串和模式串的长度
简单模式匹配的缺点:
- 时间复杂度大,因为每次匹配失败主串指针都要回溯到刚开始的位置的下一个位置重新开始匹配
如果已匹配相等的前缀序列中有某个后缀刚好是模式的前缀,那么主串指针就不用重新回溯
三、利用部分匹配值表快速匹配
KMP算法的改进思路
- 主串指针不回溯,只有模式串的指针回溯
几个概念
- 前缀:除最后一个字符外,字符串的所有头部子串
- 后缀:除第一个字符外,字符串所有尾部子串
- 部分匹配值:字符串前缀和后缀的最长相等前后缀长度
举例:‘abcac’
串 | 前缀 | 后缀 | 最长相等前后缀长度 |
---|---|---|---|
'“a” | ∅ \varnothing ∅ | ∅ \varnothing ∅ | 0 |
“ab” | a | b | 0 |
“abc” | a、ab | c、bc | 0 |
“abca” | a、ab、abc | a、ca、bca | 1 |
“abcac” | a、ab、abc、abca | c、ac、cac、bcac | 0 |
通过部分匹配值,我们可以得到部分匹配值的表
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
PM | 0 | 0 | 0 | 1 | 0 |
可以通过以下公式,配合部分匹配值
算出子串需要后移的位数
移 动 位 数 = 已 匹 配 字 符 数 − 对 应 的 部 分 匹 配 值 移动位数=已匹配字符数 - 对应的部分匹配值 移动位数=已匹配字符数−对应的部分匹配值
举例
a b a
b c a b c a c b a b a b c
发生匹配失败,则查表可知最后一个匹配的字符b
的部分匹配值为0,所以移动位数 2 − 0 = 2 2-0=2 2