c – 使用后缀数组和LCP(-LR)实现字符串模式匹配
作者:互联网
在过去的几周里,我试图弄清楚如何在另一个字符串中有效地找到字符串模式.
我发现很长一段时间,最有效的方法是使用后缀树.但是,由于这种数据结构在空间上非常昂贵,我进一步研究了后缀数组的使用(使用的空间要少得多).不同的论文,如“后缀数组:一种新的在线字符串搜索方法”(Manber& Myers,1993)指出,搜索子字符串可以在O(P log(N))中实现(其中P是通过使用二进制搜索和后缀数组以及LCP数组,模式的长度和N是字符串的长度.
我特别研究了后一篇论文来理解搜索算法. This answer在帮助我理解算法方面做得很好(顺便提一下,它已经进入了LCP Wikipedia Page).
但我仍在寻找实现此算法的方法.特别是所提到的LCP-LR阵列的构造看起来非常复杂.
参考文献:
曼伯&迈尔斯,1993年:曼伯,乌迪; Myers,Gene,SIAM Journal on Computing,1993,Vol.22(5),pp.935-948,http://epubs.siam.org/doi/pdf/10.1137/0222058
更新1
只是为了强调我感兴趣的东西:我理解LCP数组,并找到了实现它们的方法.但是,“普通”LCP阵列不适合有效的模式匹配(如参考文献中所述).因此,我对实现LCP-LR阵列感兴趣,这似乎比实现LCP阵列复杂得多
更新2
添加了参考文件的链接
解决方法:
可以帮助你的终端:增强后缀数组,用于描述带有各种其他数组的后缀数组,以替换后缀树(lcp,child).
这些可以是一些例子:
https://code.google.com/p/esaxx/ ESAXX
http://bibiserv.techfak.uni-bielefeld.de/mkesa/ MKESA
esaxx似乎正在做你想要的,另外,它有例子enumSubstring.cpp如何使用它.
如果你看一下引用的paper,它会提到一个有用的属性(4.2).由于SO不支持数学,所以没有必要在这里复制它.
我已经快速实现了,它使用了段树:
// note that arrSize is O(n)
// int arrSize = 2 * 2 ^ (log(N) + 1) + 1; // start from 1
// LCP = new int[N];
// fill the LCP...
// LCP_LR = new int[arrSize];
// memset(LCP_LR, maxValueOfInteger, arrSize);
//
// init: buildLCP_LR(1, 1, N);
// LCP_LR[1] == [1..N]
// LCP_LR[2] == [1..N/2]
// LCP_LR[3] == [N/2+1 .. N]
// rangeI = LCP_LR[i]
// rangeILeft = LCP_LR[2 * i]
// rangeIRight = LCP_LR[2 * i + 1]
// ..etc
void buildLCP_LR(int index, int low, int high)
{
if(low == high)
{
LCP_LR[index] = LCP[low];
return;
}
int mid = (low + high) / 2;
buildLCP_LR(2*index, low, mid);
buildLCP_LR(2*index+1, mid + 1, high);
LCP_LR[index] = min(LCP_LR[2*index], LCP_LR[2*index + 1]);
}
标签:c-3,c,string,pattern-matching 来源: https://codeday.me/bug/20190930/1836852.html