首先看了几位前辈的文章
http://blog.youkuaiyun.com/joylnwang/article/details/6785743
http://www.cnblogs.com/xubenben/p/3359364.html
下面这个是百科(不过我觉得百科说的不是很明白,,,,我没怎么懂。)
http://baike.baidu.com/link?url=FmEMl6OS6xUcUZr1prr9KjE8LkAKaQ3Dwz7XRIbtfal3p-YgMM_n6tZAgzEvMtjgoF2YKOYwzCE_t-fVg_moCyecPZ7zkaaW7EVh_8YoNkG
那么说一下我的看法和想法
BM其实是两种启发式方法结合
好后缀规则(detal2)和坏字符(detal1)规则
相比于KMP算法采用了两个辅助数组作为数组特征记录。
首先BM算法字符串匹配时,短串(P 即模式串)和长串(T)左对齐,之后从P串的右侧进行比对,P串的移动方向是向左,目的就是简化普通的暴力比较方法。
那么再说一下两种规则
坏字符规则
detal1数组里面记录的是 与(串中这一位字符)一样的字符 距离最右端的最近距离,因为我们是从右向左比较,所以这样
就是从P串尾开始匹配时,遇到一个不一样的字符(坏字符)时 将P串向右移动 使得串中最右端的这个字符 对齐到
坏字符前的字符
(颜色一样的代表是同一个字符)
好后缀规则
detal2数组里面记录的是 (example: at_that 的后缀 t at hat that)
后缀能否和P本身匹配并且 匹配的距离是多少。 (此处由于我们是从P的右侧开始匹配的 并且 整体需要向左移动)这样在字符匹配不成功的时候,我们就知道了它后面的后缀都是成功的,我们可以使得一部分比较被避免掉。(其实我个人觉得,可以通过后缀相同的距离,实现比较一次再不比较的方法。)也就是说我们的后缀都成功了,那么移动到与后缀相同的P中的部分和T中的这个位置对齐,我们就知道这一部分是相同的,不必重复比较了。
欢迎指正、指教与交流。
一下是我计算模式P的两个数组。
void calculateNeed(char *P, char *T){
int i,j,k,m;
int sizeP=strlen(P);
int sizeT=strlen(T);
int *delta1;//坏字符
int *delta2;//好后缀
delta1 = (int *)malloc(sizeof(int)*sizeP);
delta2 = (int *)malloc(sizeof(int)*sizeP);
delta1[0]= sizeP;//坏字符 //此字符在串中最右端的位置
for(i=1; i<=sizeP-1; i++){ //外层是每一个位的循环
for(j=sizeP-1; j>=0; j--){ //内层是每一个确定的大小
if(P[i-1]==P[j]){
delta1[i] = sizeP-1-j;
break;
}
}
}
delta2[sizeP-1]=1;//好后缀 //后面的缀可以和前面的多远一样
//其实还可以加上 每次相同的长度 但是咱这个是尾串 所以一直到末尾
//如果 P[k]一直到末尾,和j的某一个匹配的话 那么记录j 求出来delta2
for(i=sizeP-2; i>=0; i--){
k=i+1;
for(j=i; j>=0; j--){
m=j;
while(P[k]==P[m]){//判断匹配
if(k==sizeP-1){//最后一位也匹配成功了
break;
}
k++;
m++;
}
if(k==sizeP-1){
delta2[i]=sizeP - i + 1 + m - j;//7-i+n;
break;
}else{
delta2[i]=sizeP;
}
}
}
}