4.2串的模式匹配概念
BF暴力算法
//BF 暴力枚举
int index(SqString S, SqString P, int pos)
{
int i = pos - 1, j = 0;
while (i < S.length && j < P.length) {
if (S.SString[i] == P.SString[j]) {
i++; j++;//主串和子串依次匹配下一个字符
}
else {//主串、子串指针回溯重新开始下一次匹配
i = i - j + 1;//主串从下一个位置开始匹配
j = 0;//子串从头开始匹配
}
}
if (j >= P.length)
return (i - P.length);//返回匹配的第一个字符的下标
else
return -1;//模式匹配不成功
}
BF算法分析:
若设n为目标S的长度,m为模式P的长度,匹配算法最多比较n - m + 1趟。若每趟比较都比较到模式P尾部才出现不等,要做m次比较,则在最坏的情况下,总比较次数(n - m + 1) * m
在多数情况下m远小于n,因此算法运行时间为O(n*m)
低效原因:算法在字符比较不相等时,需要回溯(即i = i - j + 1):即退到s中的下一个字符开始进行继续匹配。
模式匹配的一种改进算法KMP算法:
相对BF算法有较大改进:每当一趟匹配过程出现字符不相等时,主串指示器i不用回溯,而是利用已经得到的"部分匹配"结果,将模式串向右"滑动"尽可能远的一段距离后,进行比较
KMP算法就是一种基于分析模式串P蕴含信息的改进算法
KMP算法思想:
若一趟匹配过程比对失配,在做下一趟匹配比对时,目标S的检测指针不回退,模式P右移,与S的检测指针对齐,再开始比对过程
算法的时间代价:
若每趟第一个不匹配,比较n - m + 1趟,总比较次数最坏达到(n - m) + m = n;
若每趟第m个不匹配,总比较次数最坏亦达到n
if S(s)S(s + 1)S(S + 2)...S(s+j-1) = P0 P1 P2 ... Pj - 1
if P0 P1 ... Pj-2 != P1 P2 ... Pj - 1
=> P0 P1 ... Pj-2 != S(s + 1) S(s + 2) ... S(s + j - 1)
=> 下一趟一定不匹配
if P0 P1 ... Pj - 3 != P2 P3 ... Pj - 1
则下一趟也不匹配,因为有
P0 P1 ... Pj - 3 != S(s + 2) S(s + 3) ... S(s + j - 1)
知道对于某一个k值,使得
P0 P1 ... Pk + 1 != P(j - k - 2) P(j - k - 1) ... P(j - 1)
且 P0 P1 ... Pk = P(j - k - 1) P(j - K) ... P(j - 1)
则 P0 P1 ... Pk = S(s + j - k - 1) S(s + j - k) ... S(s + j - 1)
= P(j - k + 1) P(j - k) ... P(j - 1)
== > 下一趟可以直接用P(k + 1)与S(s + j)继续比较