BM字符串匹配算法的java实现

本文提供了一段Java代码实现BM字符串匹配算法,包括构建坏字符表和好后缀表的函数,详细解释了算法原理并附有实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BM字符串匹配算法的java实现

为了方便自己下次查找,以博文形式记录


本文只提供BM字符串匹配算法的java实现,其原理请看其他文章,优快云里有讲得很好的


/**
* 函数建立一张坏字符表
* pstr: 模式串
* @param pstr
*/
public static int[] badCharacterSkip(String pstr) {
int i;
/*PS:之所以要申请256个int空间,是因为一
* 个字符是8位,所以字符可能有2^8=256种不同的情况
* */
int[] skip = new int[256];

//初始化坏字符表,256个单元全部初始化为模式串长度
for(i = 0; i < 256; i++) {
skip[i] = pstr.length();
}

i = pstr.length();
int j = 0;
/**
* 给表中需要赋值的单元赋值,但字符不在模式串pstr中时
* 应该移动pstr.length()个单位,如果字符在pstr中则移动的位置应
* 当是pstr.length()-最右索引index
*/
 
while(i != 0) {
skip[(int)pstr.charAt(j)] = i--;
j++;
}
return skip;
}

/**
* 该函数根据好后缀规则做预处理,建立一张好后缀表
* @param pstr
* @return
*/
public static int[] goodSuffixShift(String pstr) {
//模式串长度plen
int plen = pstr.length();
//好后缀表
int[] shift = new int[plen];
//记录给好后缀表赋值的位置
int sIndex = plen - 1;
//记录好后缀表边界的位置
int pIndex = plen - 1;
char c;

//保存模式串中最后一个字符,因为要反复用到它
c = pstr.charAt(plen - 1);
//以最后一个字符为边界时,确定移动距离为1
shift[plen - 1] = 1;


pIndex--;

//给shift表的每一个单元赋值
while(sIndex-- != 0) {
int p1 = plen - 2, p2, p3;
//该do...while循环完成以pIndex索引为边界时要移动的距离
do {
//该空循环,寻找与最后一个字符c匹配的字符的位置
while(p1 >= 0 && pstr.charAt(p1--) != c);
p2 = plen - 2;
p3 = p1;
//该空循环判断在边界内字符匹配到了什么位置
while(p3 >= 0 && pstr.charAt(p3--) == pstr.charAt(p2--) && p2 >= pIndex);

}while(p3 >= 0 && p2 >= pIndex);
//保存好好后缀表中,以pIndex为边界时,要移动的位置
shift[sIndex] = plen - sIndex + p2 - p3;
//边界继续向前移动
pIndex --;
}

return shift;
}

/**
* buf:文本串
* pstr: 模式串
* @param buf
* @param pstr
* @return
*/
public static boolean BMSearch(String buf, String pstr) {
int[] skip = badCharacterSkip(pstr);
int[] shift = goodSuffixShift(pstr);
int plen = pstr.length();
int blen = buf.length();
int b_idx = plen;
if(plen == 0) 
return true;
//如果文本串没到达尽头
while(b_idx <= blen) {
int p_idx = plen, skip_stride, shift_stride;
//开始匹配
while(buf.charAt(--b_idx) == pstr.charAt(--p_idx)) {
if(b_idx < 0)
return false;
if(p_idx == 0) {
return true;
}
}
//根据坏字符规则计算跳跃的距离
skip_stride = skip[(int)buf.charAt(b_idx)];
//根据好后缀规则计算跳跃的距离
shift_stride = shift[p_idx];
//取大者
b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;
}

return false;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值