我已经实现了Knuth-Morris-Pratt算法,用于在字符串B中搜索字符串A. 如果它找到字符串if返回字符串的第一个位置,则返回-1。 但现在我想计算字符串B中字符串A的总出现次数。
我尝试过一种简单的方法并且它正常工作,但这似乎并不高效,因为大字符串需要花费很多时间。
任何人都可以帮我解决这个问题吗?我希望用KMP提高效率。
这是我的考验。
public static int searchStringWithKnuthMorrisPratt(String s, String t)
{
int m=s.length();
int n=t.length();
int i=0,j=0,
k=0
;
int[] B=new int[m+1];
B[0]=-1; B[1]=0;
for (int l=2; l<=m; l++)
{
while ((k>=0) && !(s.charAt(k)==s.charAt(l-1))) k=B[k];
B[l]=++k;
}
while (i<=(n-m))
{
while ((j<m) && (s.charAt(j)==t.charAt(i+j))) j++;
if (j==m) return(i);
i=i+j-B[j];
j=Math.max(0, B[j]);
}
return(-1);
}
public static void main(String[] args)
{
String stringA = "ST";
String stringB = "XSTXXXSTX";
int count = 0;
int result = searchStringWithKnuthMorrisPratt(stringA,stringB);
while(result>-1) {
count++
stringB = stringB.substring(result+2);
result= searchStringWithKnuthMorrisPratt(stringA,stringB);
}
}
//编辑:我解决了我的问题我只需要正确阅读维基百科文章。
答案 0 :(得分:0)
你提到“用大字符串花费很多时间”。
我建议你使用Boyer Moore Horspool算法。随着模式长度的增加,它会更快。此外,使用子字符串剪切输入文本会降低性能。相反,您可以添加一个参数来指定搜索的起始点。
答案 1 :(得分:0)
“KMP with Continuation”C ++实现是here,下面是:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef unsigned long uint32;
typedef long int32;
typedef unsigned long long uint64;
typedef long long int64;
/**
* Restartable KMP Search, use as follows:
*
* uint32 h_ix = 0, n_ix = 0;
* vector<int32> kmptab = kmp_table(needle);
* for (;;) {
* h_ix = kmp_search(haystack, needle, kmptab, h_ix, n_ix);
* if (h_ix == haystack.size()) break;
*
* // found one
* n_ix = kmptab.back();
* h_ix += needle.size() - n_ix;
* }
*
* If found, returns index. If not, returns size of haystack (invalid index).
*/
vector<int32> kmp_table(vector<uint32> w);
uint32 kmp_search(const vector<uint32>& haystack, const vector<uint32>& needle, const vector<int32>& kmptab, uint32 h_ix = 0, uint32 n_ix = 0) {
while (h_ix + n_ix < haystack.size()) {
if (needle[n_ix] == haystack[h_ix + n_ix]) {
if (n_ix == needle.size() - 1) return h_ix;
n_ix++;
}
else {
h_ix += n_ix - kmptab[n_ix];
if (kmptab[n_ix] >= 0) {
n_ix = kmptab[n_ix];
}
else {
n_ix = 0;
}
}
}
/**
* Not found, return string end.
*/
return haystack.size();
}
vector<int32> kmp_table(vector<uint32> w) {
/**
* Makes for restartable search.
* Optimization idea: make input const reference, generate final value below explicitly.
*/
w.push_back(0);
uint32 pos = 2, cand = 0;
vector<int32> t(max(static_cast<int32>(2), static_cast<int32>(w.size())));
t[0] = -1;
t[1] = 0;
while (pos < w.size()) {
if (w[pos - 1] == w[cand]) {
cand++;
t[pos] = cand;
pos++;
}
else if (cand > 0) {
cand = t[cand];
}
else {
t[pos] = 0;
pos++;
}
}
return t;
}