BM是一种快于KMP的字符串匹配算法,属于启发式搜索
#include<bits/stdc++.h>
using namespace std;
int Dist(char* t, char ch)
{
int len = strlen(t), i = len - 1;
if (ch == t[i])return len;
i--;
while (i >= 0)
{
if (ch == t[i])return len - 1 - i;
else i--;
}
return len;
}
void BM(char* s, char* t)
{
int n = strlen(s), m = strlen(t), i = m - 1, j = i;
while (j >= 0 && i < n)
{
if (s[i] == t[j])
{
i--;
j--;
}
else
{
i += Dist(t, s[i]);
j = m - 1;
}
}
if (j < 0)cout << "找到了,位置在:" << i + 1;
else cout << "没找到";
}
int main(void)
{
char p1[] = "substring searching algorithm search";
char p2[] = "algorithm";
BM(p1, p2);
}
BM算法属于后缀匹配算法,顾名思义就是从模式串的后缀开始匹配。其核心思想是通过坏字符和好后缀来决定模式串后移的距离,移动距离为max(坏字符,好后缀)。
什么是坏字符,什么是好后缀
从模式串T的后缀开始,遇到的串S中第一个不匹配的字符,该字符称为坏字符。
模式串T和S所共有的最长匹配后缀称为好后缀。
坏字符规则
情况1:
S:ZXWS007
T:0 0 7
从模式串T的后缀开始匹配,可见7!=W,且W不存在于模式串T中,则直接把模式串T移动
3-(-1)=4,即直接移动到坏字符的后一位。
S:ZXWS007
T:_____007
情况2:
S:ZXWS007
T:S0 0 7
从模式串T的后缀开始匹配,可见7!=S,但S存在于模式串T中,则直接使模式串T中的S和串S中的S字符对齐,
向后移动距离=T.Length()-1-S在模式串T中最右位置
即3-0=3,模式串T向后移动3位。
S:ZXWS007
T:_____S007
好后缀规则
情况1:
S:ZXWS007
T:Z007
从模式串T的后缀开始匹配,此时模式串T中存在后缀与子串S匹配的子串:007,
移动距离=好后缀在模式串中的位置-好后缀在模式串中上一次出现的位置
4-0=4。
例子
步骤1:根据坏字符规则,模式串T移动6-(-1)=7。
移动后:
步骤2:根据坏字符规则,模式串T移动6-4=2。
移动后:
步骤3:根据好后缀规则,模式串T移动6-0=6。此步的坏字符只能移动2-(-1)=3位。故选择较大的好后缀规则。
移动后:
步骤4:根据坏字符规则,模式串T移动6-4=2。
匹配完毕: