学习好几天的BM算法,今天他来了!
为了方便操作我创建了两个文件 省的一直输入 浪费时间!
(但代码要是复制黏贴过去 需要自己穿件两个文本 在计算机的c盘的文档里 zhuchuan zichuan)
思路
好后缀和坏字符法一起用;分别放入不同的函数中 将x i j指针传入函数,返回位移量;好后缀还需要用到另外新建一个指针j
这里用到坏字符规则
这里写的是好后缀的过程 当然程序写的时候还得都比较一下
好后缀中,y和j比较 再和j-1比较都不相同,若有相同的则把y向后移动一位 再与j-1比较、
这里a位移到c下边是因为怕有漏的;一样的,如果有三个字符的好后缀则移动到第二个好后缀下;
此处坏字符规则;
此处好后缀
此时匹配完成;
速度非常快;
测试:
这里我为了更好看见代码的错误,是分开用坏字符和好后缀的 最后再给两个加个比较看哪个位移量跟多 就选哪一种方式;
若你自己写的好后缀或坏字符代码,可以测试这几个
坏字符:
1.
主abcdabca
子abca
2.
主abcbabca
子abca
3.
主abcbacab
子acab
4.
主abcbabab
子abab
好后缀
1.
abcdababacab
abacab
2.
abcdabbacdab
bacdab
3.
abcdababcdba
abcdba
4.
abcdabbacdaa
bacdaa
最后再来一个 综合的
abcdabbacdababcdba
abcdba
当然,一个好的代码一定得经得住上万字符搜索的操作;可以随机输入几百个字符然后复制黏贴,让代码跑起来;看还能搜做到不;
例如:
子串是:abcdbaabcdbaabcdba
运行结果:
没有出错就很舒服:
得劲儿!!!!!!!!!!!!!!
不多bibi 上代码:
代码介绍:
文件操作就不介绍了 之前写过好多次了;
这里是坏字符原则代码:
int huai(int i,int j,int x)//坏字符
{
int y=0;
while(str[j]==stri[x])//选取坏字符时后面可能有相同的字符此时需要跳过;
{
j--;
x--;
if(j<0)//此时是判断是否匹配成功;
return -1;
}
while(str[j]!=stri[x])//这里是检测坏字符;直到找到相同的时跳出,y就是位移量;
{
if(str[j]!=stri[x])
{
j--;
y++;
}
if(j<=0)//这里是怕匹配的都不相同,这时位移量挺大的;
return y;
}
if(x>=zhushu-1)//当时调试代码是老是溢出 我就设置了一下终点;
{
printf("没找到\n");
return -2;
}
return y;
}
好后缀原则代码:
int hao(int i,int j,int x)//好后缀
{
int y=0;
int m,n,z;
while(str[j]!=stri[x])//把好后缀后边的不相同的跳过;
{
if(j<0)//处理当字符都不相同时的情况;
return 1;
j--;
x--;
if(x>zhushu-1)//此时也是防止溢出 zhushu是主字符数组字符的总长
return -2;
}
i=x;//若主串前半部分不相等 则m和i x不相等
z=0;
while(str[j]==stri[x])//遇到相同的字符把x 和j向前移动; 方便后边匹配;
{
x--;
j--;
z++;
//
if(z==zong)//当z与子串总长相同时 匹配成功!
return -1;
if(j<0)//同上 可忽略;
return 1;
}
while(1)//此时x已指向相同后边的字符 之后遇到相同字符相同时需要移动i 若i和x未相等字符不匹配了 这是i利用m回归原位再进行匹配;
{
m=i;
while(str[j]==stri[i])
{
i--;
j--;
y++;
if(j<0)
break;
if(i==x)
break;
}
if(j<0)
break;
while(str[j]!=stri[i])
{
i=m;
j--;
y++;
if(j<0)
break;
if(i==x)
break;
}
if(j<0)
break;
if(i==x)//到这里说明符合了好后缀原则 找到了 与好后缀相同的字符 返回位移量
break;
}
if(y==zong)
return -1;
return y;
}
这个是选择好后缀还是坏字符代码:
void chazhao()
{
printf("主串长度%d 子串长度%d\n",zhushu,zong);
int x=zong-1,i=zong-1,j=zong-1;//从0开始计算zong-1, 最后结尾时也是zhushu-1与他相等;
int huaifan=0,haofan=0;
while(1)
{
huaifan=huai(i,j,x);//函数
haofan=hao(i,j,x);
if(huaifan>=haofan)
{
x=x+huaifan;
i=x;
j=zong-1;
}
else
{
x=x+haofan;
i=x;
j=zong-1;
}
if(huaifan==-1||haofan==-1)
{
x++;
printf("\n子串在主串%d的位置\n",x);
break;
}
if(huaifan==-2)
break;
if(haofan==-2)
{
printf("没找到!\n");
break;
}
}
return;
}
完整代码:
//BM算法;
#include<stdio.h>
#include<stdlib.h>
char str[50];//子串
char stri[10000000];//主串长度 修改处
int zhushu;//主串总字符
int zong; //子串总字符
void shuru();
void shuchu();
void chazhao();
int huai(int i,int j,int x);
int hao(int i,int j,int x);
int main()
{
shuru();
chazhao();
shuchu();
}
//===============================================================
void shuru()
{
FILE *fp,*fq;
int h,e;
if((fp = fopen("zichuan.txt","r")) == NULL)//输入子串字符
{
printf("can not open this file \n");
exit(0);
}
h=ftell(fp);
fseek(fp,0,2);
e=ftell(fp);
fseek(fp,0,0);
zong=e;
while(e-h>0)//文件中的字符导入到子字符数组
{
//printf("%d %d ",h,e);
fscanf(fp,"%c",&str[h]);//一个回车 三个字符去存它 会使字符数组增加三个
h++;
}
fclose(fp);
if((fq = fopen("zhuchuan.txt","r")) == NULL)//输入主串字符
{
printf("can not open this file \n");
exit(0);
}
h=ftell(fq);
fseek(fq,0,2);
e=ftell(fq);
fseek(fq,0,0);
//printf(" h=%d\n ",h);
zhushu=e-h;
while(e-h>0)//文件中的字符导入到主字符数组;
{
fscanf(fq,"%c",&stri[h]);
// printf("%c ",stri[h]);
h++;
}
fclose(fq);
}
//========================================================
void shuchu()
{
int i=0;
while(i<zong)
{
printf("%c",str[i]);
i++;
}
i=0;
printf("\n");
while(i<zhushu)
{
printf("%c",stri[i]);
i++;
}
}
//==========================================
void chazhao()
{
printf("主串长度%d 子串长度%d\n",zhushu,zong);
int x=zong-1,i=zong-1,j=zong-1;//从0开始计算zong-1, 最后结尾时也是zhushu-1与他相等;
int huaifan=0,haofan=0;
while(1)
{
huaifan=huai(i,j,x);
haofan=hao(i,j,x);
if(huaifan>=haofan)
{
x=x+huaifan;
i=x;
j=zong-1;
}
else
{
x=x+haofan;
i=x;
j=zong-1;
}
if(huaifan==-1||haofan==-1)
{
x++;
printf("\n子串在主串%d的位置\n",x);
break;
}
if(huaifan==-2)
break;
if(haofan==-2)
{
printf("没找到!\n");
break;
}
}
return;
}
//===========================================================
int huai(int i,int j,int x)//坏字符
{
int y=0;
while(str[j]==stri[x])
{
j--;
x--;
if(j<0)
return -1;
}
while(str[j]!=stri[x])
{
if(str[j]!=stri[x])
{
j--;
y++;
}
if(j<=0)
return y;
}
if(x>=zhushu-1)
{
printf("没找到\n");
return -2;
}
return y;
}
//+===============================================
int hao(int i,int j,int x)//好后缀
{
int y=0;
int m,n,z;
while(str[j]!=stri[x])
{
if(j<0)
return 1;
j--;
x--;
if(x>zhushu-1)
return -2;
}
i=x;//若主串前半部分不相等 则m和i x不相等
z=0;
while(str[j]==stri[x])
{
x--;
j--;
z++;
if(z==zong)
return -1;
if(j<0)
{
return 1;
}
}
while(1)
{
m=i;
while(str[j]==stri[i])
{
i--;
j--;
y++;
if(j<0)
break;
if(i==x)
break;
}
if(j<0)
break;
while(str[j]!=stri[i])
{
i=m;
j--;
y++;
if(j<0)
break;
if(i==x)
break;
}
if(j<0)
break;
if(i==x)
break;
}
if(y==zong)
return -1;
return y;
}
//abcdabbbacdababcdba
// abcdba
//aaaaab
//aaaab