Algorithm 比BMH(Boyer&"x2013;Moore&"x2013;Horspool)搜索更快的算法
您将使用哪种算法在短文本中搜索短子字符串?简而言之,我的意思是5-10个字符代表子字符串,255个字符代表字符串。我正在考虑根据输入数据长度选择算法。对于较长的输入,哪种算法更好?试试。但是,对于这样短的字符串,通常的线性扫描就足够了。您可以尝试或。两者都取决于模式的长度。如果你正在寻找一种比Boyer Moore更好的算法,那么你要求的是混合答案 据我所知,在文本搜索中,只有后缀树优于Boyer-Moore。但是,它使用更多的时间来创建索引,并使用更多的磁盘空间 其他信息: 在速度方面,后缀树或后缀数组胜过任何版本的Boyer-Moore,因为后缀树基本上实现了树状数据结构中所有可能的搜索 但是,后缀树具有较高的ram内存成本,并且索引文本(创建树数据结构)的速度较慢 Boyer Moore与后缀树的速度差异: Boyer Moore在搜索文本上是线性的。 后缀树在搜索模式上是线性的 如果在200个字符的文本中搜索5个字母单词,boyer moore将执行200次操作,后缀树将执行5次操作 无论它的速度有多快,都很难实现。就数据结构的难度而言,它可能是最难的。一旦建成,它可以大大优化空间和速度 这就是说,在未来几年中寻找后缀树。 通常,后缀树用于DNA索引和web搜索引擎优化 Boyer Moore被广泛应用于各个领域,例如会议程序(文本搜索功能)和网络搜索引擎。@anon@Anton GogolevAlgorithm 比BMH(Boyer&"x2013;Moore&"x2013;Horspool)搜索更快的算法,algorithm,search,string,full-text-search,Algorithm,Search,String,Full Text Search,您将使用哪种算法在短文本中搜索短子字符串?简而言之,我的意思是5-10个字符代表子字符串,255个字符代表字符串。我正在考虑根据输入数据长度选择算法。对于较长的输入,哪种算法更好?试试。但是,对于这样短的字符串,通常的线性扫描就足够了。您可以尝试或。两者都取决于模式的长度。如果你正在寻找一种比Boyer Moore更好的算法,那么你要求的是混合答案 据我所知,在文本搜索中,只有后缀树优于Boyer-Moore。但是,它使用更多的时间来创建索引,并使用更多的磁盘空间 其他信息: 在速度方面,后缀树
用一个词回答你的问题: 四联轨道炮 这个C函数在短的2,3,4模式和160个字符的字符串上进行了大量测试,您可以在这个表中自行决定 还有一篇文章:
我认为Boyer-Moore Horspool可以通过这种变化更快(我不知道它的名字,也许我的名字:-))。BMH算法没有利用匹配字符和非匹配字符信息。它仅使用当前图案位置中的最后一个文本字符。例如:
Pattern: ABCABC
012345
在BMH中,下一个位置是(C与下一个C对齐):
如果我们使用匹配的字符,下一个位置是(BC与下一个BC对齐):
如果我们使用匹配字符和不匹配字符,下一个位置是(BC与下一个BC对齐,但由于不匹配的模式字符A与下一个BC的上一个字符相同,因此也将不匹配。由于没有其他BC,跳过的是模式长度):
这是Java实现(仍然可以改进),使用风险自负,因为我还没有彻底测试它。在我的性能测试中,Boyer Moore Horspool在所有方面仍然优于此实现。但正如预期的那样,如果模式被重用(两者都没有模式预处理),那么这个实现将获胜
public static int[] processPattern1(char[] pattern) {
int[] skip = new int[256];
for (int i = 0; i < skip.length; ++i) {
skip[i] = pattern.length;
}
for (int i = 0; i < pattern.length - 1; ++i) {
skip[pattern[i]] = pattern.length - i - 1;
}
return skip;
}
public static int[] processPattern2(char[] pattern) {
int[] skip = new int[pattern.length];
int i, j, k, x, y;
int lpos = pattern.length - 1;
int l2pos = pattern.length - 2;
OUTER:
for (k = l2pos; k > -1; k--) { // k points to unmatched pattern character
j = k + 1;
for (i = k; i > 0; i--) {
if (pattern[i] == pattern[j] && pattern[i-1] != pattern[k]) {
for (x = i + 1, y = j + 1; y < pattern.length && pattern[x] == pattern[y]; x++, y++) {
}
if (y == pattern.length) {
skip[k] = pattern.length - x;
continue OUTER;
}
}
}
for (x = lpos - j; x > -1; x--) {
if (pattern[x] == pattern[lpos]) {
for (i = x - 1, y = l2pos; i > -1 && pattern[i] == pattern[y]; i--, y--) {
}
if (i == -1) {
skip[k] = lpos - x;
continue OUTER;
}
}
}
skip[k] = pattern.length;
}
return skip;
}
public static int search(char[] text, char[] pattern, int[] skip1, int[] skip2) {
int k = pattern.length - 1;
int i, j;
int lpos = k;
int l2pos = pattern.length - 2;
while (k < text.length) {
if (text[k] == pattern[lpos]) {
for (j = l2pos, i = k - 1; j > -1 && text[i] == pattern[j]; j--, i--) {
}
if (j == -1) {
return i + 1;
}
k += skip2[j];
} else {
k += skip1[text[k]];
}
}
return -1;
}
public static void main(String[] args) {
String origText = "TTTTTTTTTTTTTTTZBCRABCCABCTTTTTTTTTTTTT";
char[] pattern = "ZBCRABCCABC".toCharArray();
char[] text = origText.toCharArray();
int[] skip1 = processPattern1(pattern);
int[] skip2 = processPattern2(pattern);
System.out.println(search(text, pattern, skip1, skip2) == origText.indexOf(pattern));
}
publicstaticint[]processPattern1(char[]pattern){
int[]跳过=新int[256];
对于(int i=0;i-1;k--){//k指向不匹配的模式字符
j=k+1;
对于(i=k;i>0;i--){
if(模式[i]==模式[j]&模式[i-1]!=模式[k]){
对于(x=i+1,y=j+1;y-1;x--){
if(模式[x]==模式[lpos]){
对于(i=x-1,y=l2pos;i>-1&&pattern[i]==pattern[y];i--,y--){
}
如果(i==-1){
skip[k]=lpos-x;
继续对外开放;
}
}
}
跳过[k]=模式长度;
}
回程箕斗;
}
公共静态int搜索(char[]文本,char[]模式,int[]skip1,int[]skip2){
int k=模式长度-1;
int i,j;
int-lpos=k;
int l2pos=pattern.length-2;
while(k-1&&text[i]==pattern[j];j--,i--){
}
如果(j==-1){
返回i+1;
}
k+=skip2[j];
}否则{
k+=skip1[文本[k]];
}
}
返回-1;
}
公共静态void main(字符串[]args){
字符串origText=“ttttttttt zbcracabctttttttttttttt”;
char[]pattern=“zbcrabc.toCharArray();
char[]text=origText.toCharArray();
int[]skip1=processPattern1(模式);
int[]skip2=processPattern2(模式);
System.out.println(搜索(文本、模式、skip1、skip2)=origText.indexOf(模式));
}
以下是我对上述代码的改进。在我的测试中,它与BMH并驾齐驱,但在某些情况下会取得相当大的成功(每次运行是对39650个字符的英文文档的随机位置进行1000000次搜索)
公共类BoyerMoore{
int[]tab1=新int[256];
int[]tab2=新int[1000][1001];
int[]tab3=新int[1000];
公共场所{
for(int i=0;iText : TTTTZBCTTTTTTTTTTTTT
Pattern: ABCCABC
Text : TTTTZBCTTTTTTTTTTTTT
Pattern: ABCCABC
public static int[] processPattern1(char[] pattern) {
int[] skip = new int[256];
for (int i = 0; i < skip.length; ++i) {
skip[i] = pattern.length;
}
for (int i = 0; i < pattern.length - 1; ++i) {
skip[pattern[i]] = pattern.length - i - 1;
}
return skip;
}
public static int[] processPattern2(char[] pattern) {
int[] skip = new int[pattern.length];
int i, j, k, x, y;
int lpos = pattern.length - 1;
int l2pos = pattern.length - 2;
OUTER:
for (k = l2pos; k > -1; k--) { // k points to unmatched pattern character
j = k + 1;
for (i = k; i > 0; i--) {
if (pattern[i] == pattern[j] && pattern[i-1] != pattern[k]) {
for (x = i + 1, y = j + 1; y < pattern.length && pattern[x] == pattern[y]; x++, y++) {
}
if (y == pattern.length) {
skip[k] = pattern.length - x;
continue OUTER;
}
}
}
for (x = lpos - j; x > -1; x--) {
if (pattern[x] == pattern[lpos]) {
for (i = x - 1, y = l2pos; i > -1 && pattern[i] == pattern[y]; i--, y--) {
}
if (i == -1) {
skip[k] = lpos - x;
continue OUTER;
}
}
}
skip[k] = pattern.length;
}
return skip;
}
public static int search(char[] text, char[] pattern, int[] skip1, int[] skip2) {
int k = pattern.length - 1;
int i, j;
int lpos = k;
int l2pos = pattern.length - 2;
while (k < text.length) {
if (text[k] == pattern[lpos]) {
for (j = l2pos, i = k - 1; j > -1 && text[i] == pattern[j]; j--, i--) {
}
if (j == -1) {
return i + 1;
}
k += skip2[j];
} else {
k += skip1[text[k]];
}
}
return -1;
}
public static void main(String[] args) {
String origText = "TTTTTTTTTTTTTTTZBCRABCCABCTTTTTTTTTTTTT";
char[] pattern = "ZBCRABCCABC".toCharArray();
char[] text = origText.toCharArray();
int[] skip1 = processPattern1(pattern);
int[] skip2 = processPattern2(pattern);
System.out.println(search(text, pattern, skip1, skip2) == origText.indexOf(pattern));
}
public class BoyerMoore {
int[] tab1 = new int[256];
int[][] tab2 = new int[1000][1001];
int[] tab3 = new int[1000];
public BoyerMoore8() {
for (int i = 0; i < tab1.length; i++) {
tab1[i] = -1;
}
}
public void processPattern(char[] pattern) {
// tab1 structure,
// 0 => tab2 index
// tab2 structure,
// 0 - pattern length - 2 => skip values
// pattern length - 1 => default skip value
// pattern length => pattern position where to start comparing
int i, p;
int lp = pattern.length - 1;
for (i = 0; i < pattern.length; ++i) {
tab3[i] = tab1[pattern[i]];
tab1[pattern[i]] = i;
}
for (i = pattern.length - 2; i > -1; i--) {
if (i < tab1[pattern[i]]) {
continue;
}
p = tab1[pattern[i]];
tab2[p][lp] = lp - i;
tab2[p][pattern.length] = i - 1;
computeJump(pattern, p, i + 1, tab2[p][lp]);
}
computeJump(pattern, tab1[pattern[lp]], pattern.length, 0);
}
public void computeJump(char[] pattern, int index, int len, int defJump) {
int i, k, x, y;
int lpos = len - 1;
int l2pos = len - 2;
int p = tab3[lpos];
OUTER1:
for (k = 0; k < lpos; k++) { // k points to unmatched pattern character
i = tab3[k + 1];
OUTER2:
while (i > 0) {
if (pattern[i - 1] != pattern[k]) {
x = k + 2;
y = i + 1;
while (x < len) {
if (pattern[y++] != pattern[x++]) {
i = tab3[i];
continue OUTER2;
}
}
tab2[index][k] = (len - y) + defJump;
continue OUTER1;
} else {
i = tab3[i];
}
}
x = l2pos - k;
while (p > x) {
p = tab3[p];
}
i = p;
OUTER3:
while (i > -1) {
x = l2pos;
y = i - 1;
while (y > -1) {
if (pattern[y--] != pattern[x--]) {
i = tab3[i];
continue OUTER3;
}
}
tab2[index][k] = (lpos - i) + defJump;
continue OUTER1;
}
tab2[index][k] = len + defJump;
}
}
public int search(char[] text, char[] pattern) {
int k = pattern.length - 1;
int i, j, p;
int lpos = k;
int l2pos = k - 1;
OUTER:
while (k < text.length) {
p = tab1[text[k]];
if (p == -1) {
k += pattern.length;
continue OUTER;
} else {
if (text[k] == pattern[lpos]) {
for (j = l2pos, i = k - 1; j > -1; j--, i--) {
if (text[i] != pattern[j]) {
k += tab2[p][j];
continue OUTER;
}
}
return i + 1;
} else {
for (j = tab2[p][pattern.length], i = k - 1; j > -1; j--, i--) {
if (text[i] != pattern[j]) {
k += tab2[p][j];
continue OUTER;
}
}
k += tab2[p][lpos];
continue OUTER;
}
}
}
return -1;
}
public int search(String origText, String origPattern) {
char[] text = origText.toCharArray();
char[] pattern = origPattern.toCharArray();
processPattern(pattern);
int res = search(text, pattern);
for (int i = 0; i < pattern.length; i++) {
tab1[pattern[i]] = -1;
}
return res;
}
}
Pattern: ABCABC
012345
public class BoyerMooreHorspool {
int[] tab1 = new int[256];
int[][] tab2 = new int[1000][1000];
int[] tab3 = new int[1000];
public BoyerMooreHorspool() {
for (int i = 0; i < tab1.length; i++) {
tab1[i] = 999;
}
for (int i = 0; i < 1000; i++) {
tab2[999][i] = -1;
}
}
public void processPattern(char[] pattern) {
int i, j, p;
for (i = 0; i < pattern.length; ++i) {
tab1[pattern[i]] = -1;
}
for (i = 0; i < pattern.length; ++i) {
tab3[i] = tab1[pattern[i]];
tab1[pattern[i]] = i;
}
for (i = 0; i < pattern.length; i++) {
p = tab1[pattern[i]];
for (j = tab3[i] + 1; j < i; j++) {
tab2[p][j] = tab3[i];
}
if (i == p) {
for (j = i; j < pattern.length; j++) {
tab2[p][j] = i;
}
} else {
tab2[p][i] = i;
}
}
}
public int search(char[] text, char[] pattern) {
int k = pattern.length - 1;
int i, j, oi, ok;
int lpos = k;
while (k < text.length) {
j = k;
ok = k;
i = tab2[tab1[text[j]]][lpos];
k += lpos - i;
j--;
i--;
while (i > -1) {
oi = i;
i = tab2[tab1[text[j]]][i];
k += oi - i;
j--;
i--;
}
if (ok == k) {
return j + 1;
}
}
return -1;
}
public int search(String origText, String origPattern) {
char[] text = origText.toCharArray();
char[] pattern = origPattern.toCharArray();
processPattern(pattern);
int res = search(text, pattern);
for (int i = 0; i < pattern.length; i++) {
tab1[pattern[i]] = 999;
}
return res;
}
}