本文要在掌握了Kmp算法的基础上阅读比较妥当
Horspool和Kmp算法有点相识,都是采用空间换时间的想法,从而达到算法运算速率的提高,运算效率也都是θ(n),在最佳情况下,它的时间复杂度是O(n/m),
不过,Horspool也有自己的不同点:
1、每次匹配不正确时,移动的算法和Kmp不一样
2、采用模式从右到左的匹配,一旦匹配不正确,模式串相对文本串移动table[i]个字符
先看一下该算法执行的移动过程
字符c | A | B | C | D | E | F | ... | R | ... | Z | - |
移动距离 | 4 | 2 | 6 | 6 | 1 | 6 | 6 | 3 | 6 | 6 | 6 |
J I M _ S A W _ M E _ I N _ A _ B A R B E R S H O P
BAR B E R B A R B E R
B A R B E R B A R B E R
B A R B E R B A R B E R
B A R B E R
table 2 4 3 2 1 3
接下类我们看一下他的移动数据数组是怎么求的
t(c) = {模式的长度m 如果c不包括在模式的前m-1个字符中)
模式前m-1个字符中最右边的c到模式最后一个字符的距离 (其他情况)
/**
* 输入: 模式p[0..m-1]以及一个可能出现字符的字母表 输出: 以字母表中字符为索引的数组table[0..size-1] <br/>
* 把模式串没有的字符table设为m,有的设为m-1-i,i以模式中当前字符位置最小值
*
* @param m
* 模式串
* @return
*/
public static int[] shiftTable(char m[])
{
int[] table = new int[255];
int len = m.length;
// 把模式串没有的字符table设为m,有的设为m-1-i,i以模式中当前字符位置最小值
Arrays.fill(table, len);
// 这里边界为len-1,len-1得为吗,如果位置为0时,死循环
for (int i = 0; i < len - 1; i++)
{
table[m[i]] = len - 1 - i;
}
return table;
}
匹配过程
/**
* 匹配过程
*
* @param m 模式串
* @param t 文本串
* @return
*/
public static int horspoolMatching(char m[], char[] t)
{
int[] table = shiftTable(m);
int mLen = m.length;
int tLen = t.length;
// 当前匹配模式串位置,由末尾开始匹配
int i = mLen;
// 匹配模式字符串字符个数
int k;
while (i < tLen)
{
k = 0;
while (k < mLen && t[i - 1 - k] == m[mLen - 1 - k])
k++;
// 当匹配个数等于模式串个数
if (k == mLen)
return i - mLen;
else
i += table[t[i - 1]];
}
return -1;
}
测试程序
public static void main(String[] args)
{
String mS = "abcbdc";
String tS = "sdfabcdabcbdcsd";
// 打印返回的下标值
System.out
.println(horspoolMatching(mS.toCharArray(), tS.toCharArray())); //输出7
}
args[0] BARBER
args[1] JIM_SAW_ME_IN_A_BARBERSHOP
输出:16