BM算法,著名的字符串匹配算法。 嘿嘿我称它为“ctrl+F”算法。
看了好几篇博客,我把我的学习过程简单做个笔记。给自己以后“复习”留点思路,也希望对大家有点用。
今天从对此算法一无所知到自己写出来的过程如下。
首先,仔细看了大神的一片博客。
http://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html
由于作者写的清晰明了,导致我以为此算法很简单。
于是,就想动手写。但是,看了几个网上的代码后我直接蒙了。
那么详细的注释竟然没看懂。
于是找了几篇详细介绍编程思想的关于BM算法的博客。
http://blog.chinaunix.net/uid-23390992-id-3320412.html//这个我只能说一图胜过千言万语 赞!!
http://blog.youkuaiyun.com/eric491179912/article/details/6210009
http://blog.youkuaiyun.com/zdp072/article/details/13168605
由于不会弄图。只好拿作者的图借来用了。
他们把算法过程都介绍的很详细,我就不赘述了,就讲几点我遇到问题的点。
一、写坏后缀表借鉴了
http://blog.youkuaiyun.com/zdp072/article/details/13168605
的代码。那个用字符的asc码做下标真的很赞。
二、写好后缀表
我写的代码思路是受下面这篇博客的影响。
http://blog.youkuaiyun.com/eric491179912/article/details/6210009
但是,下面这些代码思路,即关于那三种情况的代码怎么来的还是不清楚。
直到我遇见了他。
http://blog.chinaunix.net/uid-23390992-id-3320412.html
博主下面的这张图画的太赞了。完美解释了三种情况。
好了,看了他们的博客你也可以自己写了(自己不会画图,所以就不分析了)。
下面就上我写的程序。刚刚完成。用的那个例子,没问题,其他没测试。可能很多bug吧。你就看下对你有用的地方就好。
--------------------------程序源码
/*
BM 算法
*/
public class bbmm{
final static int CHAR_MAX=256;//256是为了asc码的个数考虑
//------------获取坏后缀表
public static int[] getBad(String s){
int[] bad = new int[CHAR_MAX];
//初始化
for (int i=0;i<CHAR_MAX ;i++ ) {
bad[i]=-1;
}
for (int i=0;i<s.length();i++ ) {
//在这里字符转asc码 做字符所在位置的映射
bad[s.charAt(i)]=i;
}
return bad;
}
//-------------hao的辅助数组buff[]
public static int[] getBuff(String p,String s){
int flag;
int m=s.length();
int[] buff = new int[CHAR_MAX];
//最后一个肯定是P串
buff[m-1]=m;
for (int i=m-2;i>=0 ;i-- ) {
flag=i;
while((s.charAt(flag)==p.charAt(m-1-(i-flag)))&&(flag>=0))
flag--;
buff[i]=i-flag;
}
return buff;
}
//--------------获取好后缀表
public static int[] getHao(String p,String s){
int m=s.length();
int[] buff=getBuff(p,s);
int[] hao = new int[CHAR_MAX];
//第三种情况
for (int i=0;i<s.length() ;i++ ) {
hao[i]=m;
}
//第二种情况
for (int i=m-1;i>=0 ;i-- ) {
//关键点 buff[i]=i+1;来判断第二种情况
if(buff[i]==(i+1)){
for (int j=i;j<m-1-(buff[i]) ;j++ ) {
if(hao[i]==m)
hao[j]=m-1-i;
}
}
}
//第一种情况
for (int i=0;i<m-1 ;i++ ) {
hao[m-1-buff[i]]=m-1-i;
}
return hao;
}
//--------------BM查找
public static int bmFind(String p,String s){
int[] hao = getHao(p,s);
int[] bad = getBad(s);
int pl= p.length();
int sl=s.length();
int i=0;
while(pl>sl+i){
int j=sl-1;
while(s.charAt(j)==p.charAt(i+j)){
if (j>=0) {
j--;
}
}//while
if(j<0) break;
else if(hao[j]>(j-bad[p.charAt(i+j)])){
i+=hao[j];
}else {
i+=j-bad[p.charAt(i+j)];
}
}
return i;
}
//---------------main函数
public static void main(String[] args) {
String p = "HERE IS A SIMPLE EXAMPLE";
String s = "EXAMPLE";
System.out.print("字符串位置: ~"+bmFind(p,s));
}
}