BM算法学习小记

 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));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值