//BM algorithm
/*
1: bmbc[p[i]]:p中最右边出现的p[i]字符到p最后一个字符的步长(plen-1-i),但不是坏字符时需要主串移动的步长
2: suffix[i]:p[i]往前推(包括p[i]),与p[len-1]往前推(包括p[len-1]),的最大匹配长度(匹配字符个数)
3: bmgs[i]:p中能够最大匹配p[i+1]到p[len-1]字符的步长,其是好后缀时主串需要移动的步长。分三种情况,p中有完全匹配的,
p的开始和结束部分匹配的,完全不匹配的!
*/
#include <iostream.h>
#include <string.h>
#define CHARMAX 128
void init_BMBC(int* bmbc, char* p, int p_len);
void getSuffix(char* p, int* suffix, int p_len);
void init_BMGS(int* bmgs, char* p, int p_len);
int BM_Search(char* t,char* p);
void show(char* intro, int* out, int len, char* p);
void init_BMBC(int* bmbc, char* p, int p_len)
{
for(int i=0; i<CHARMAX; i++)
bmbc[i]=p_len;
for(i=0; i<p_len; i++)
{
bmbc[p[i]]=p_len-i-1;//bmbc[p[i]]:p[i]到p最后的距离
}
show("bmbc",bmbc,p_len,p);
}
void getSuffix(char* p, int* suffix, int p_len)
{
suffix[p_len-1]=0;
for(int i=p_len-2; i>=0; i--)
{
int m=p_len-1;//m为p的最后下标
int n=i;
while(n>=0 && p[n]==p[m])
{
n--;
m--;
}
suffix[i]=i-n;
}
show("suffix",suffix,p_len,NULL);
}
void init_BMGS(int* bmgs, char* p, int p_len)
{
int* suffix=new int[p_len];
getSuffix(p,suffix,p_len);
//to do...
bmgs[p_len-1]=0;
for(int i=p_len-2; i>=0; i--)
{
int goodSuffixlen=p_len-1-i;
bool bmgsFlag=false;
for(int j=p_len-2; j>=p_len-1-i; j--)
{
if(goodSuffixlen<=suffix[j])//注意是小于等于,而不是等于,因为小于时,suffix包含了好后缀
{
bmgs[i]=p_len-1-j;
bmgsFlag=true;
break;
}
}
if(!bmgsFlag)
{
for(int j=p_len-2-i; j>=0; j--)
{
if(suffix[j]==j+1)
{
bmgs[i]=p_len-1-j;
bmgsFlag=true;
break;
}
}
}
if(!bmgsFlag)
{
bmgs[i]=p_len;
}
}
show("bmgs",bmgs,p_len,NULL);
delete suffix;
}
int BM_Search(char* t,char* p)
{
int t_len=strlen(t);
int p_len=strlen(p);
int bmbc[CHARMAX];
int* bmgs=new int[p_len];
init_BMBC(bmbc,p,p_len);
init_BMGS(bmgs,p,p_len);
int k=p_len-1;//k:其为主串的开始匹配位置,每次移动都是移动的k
while(k<t_len)
{
int i=k;
int j=p_len-1;
while(j>=0 && t[i]==p[j])
{
i--;//主串中开始比较的位置
j--;//模式串中开始比较的位置
}
if(j<0)
{
delete bmgs;
return k-p_len+1;
}
else
{
int step=bmgs[j]>=(bmbc[t[i]]-p_len+1+j) ? bmgs[j] : (bmbc[t[i]]-p_len+1+j);
k+=step;
}
}
delete bmgs;
return -1;
}
void main()
{
char* t="abcdefegadfefdsfeabcgfabcabcabcffabcabcaafde";
char* p="abcffabcabc";
cout<<"t: "<<t<<"\n"<<"p: :"<<p<<"\n\n";
cout<<"\nmatch position: "<<BM_Search(t,p)<<endl;
}
void show(char* intro, int* out, int len, char* p)
{ cout<<intro<<": ";
if(!p)
for(int i=0; i<len; i++)
cout<<out[i]<<" ";
else
for(int i=0; i<len; i++)
cout<<out[p[i]]<<" ";
cout<<endl;
}
BM algorithm
最新推荐文章于 2021-01-08 13:33:50 发布