启发式的BoyerMoor字符串查找算法
本文参考《算法(第4版)》
图示:
启发式的BoyerMoor字符串查找算法的指导思想是,每次从右向左扫逐个描模式串和文本串,不匹配时则模式串向右移动一定距离。
使用一个right[]数组存放文本字符串中每个字符在模式串中最右的位置。文本字符串必是字母表中的字符,由于输入文本字符未知,所以这里计算字母表中的所有字符在模式串中最右的位置。
查找是从左向右扫描文本字符串,从右向左扫描模式字符串,将模式和文本最左端对齐。使用一个文本指针i指向文本字符串最左端,使用一个指针j指向模式串最右端,比较txt[i+j]和pat[j]是否匹配,匹配则j向左移动一位继续比较比较txt[i+j]和pat[j]。若j移动到最左端,即j=0时仍匹配,则说明文本串中存在一个匹配的模式串。
不匹配的情况有三种:
文本字符和模式字符不匹配时,且模式中不存在该文本字符,则指针i 向右移动j - right[i+j] 。由于模式中不存在该文本字符,所以此时right[i+j] = -1,则 i 向右移动的距离为 j - right[i+j] = j + 1, 并将 j 复位为 M - 1,即模式串最右端。
文本字符和模式字符不匹配时,且该文本字符在模式串存在且出现在不匹配的模式字符的左边,则 i 向右移动 j - right[i+j],j 复位为 M - 1。
文本字符和模式字符不匹配时,且该文本字符在模式串存在且出现在不匹配的模式字符的右边,此时为了模式字符和文本字符匹配,相当于模式串相对于文本字符串向左移动,为避免此情况发生,可设置 i = i + 1,即文本指标 i 向右移动一位,继续下一次查找。j 复位为 M - 1。
1.实现代码
package algorithms.stringrank;
public class BoyerMoor {
String pat;
int[] right;
public BoyerMoor(String pat){
this.pat = pat;
int M = pat.length();
int R =256;
this.right = new int[R];
for(int c = 0; c < R; c++)
right[c] = -1;
for(int j = 0; j < M; j++)
right[this.pat.charAt(j)] = j;
}
public int search(String txt){
int N = txt.length();
int M = pat.length();
int skip;
for(int i = 0; i <= N-M; i+=skip){
skip = 0;
for(int j = M-1; j >= 0; j--)
if(txt.charAt(i+j) != pat.charAt(j)){
skip = j - right[txt.charAt(i+j)];//在不等情况下skip不可能等于0;
if(skip < 1) skip = 1;
break;
}
if(skip == 0) return i;
}
return N;
}
public static void main(String[] args) {
BoyerMoor bm = new BoyerMoor("bike");
int j = bm.search("aboombikemike");
System.out.println(j);
j = bm.search("aboombyikemike");
System.out.println(j);
}
}
输出:
5
14