1

我已经实现了用于在字符串 B 中搜索字符串 A 的 Knuth-Morris-Pratt 算法。如果找到该字符串,则返回字符串的第一个位置,否则返回 -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);

              }
}

//编辑:我解决了我的问题,我只需要正确阅读维基百科文章。

4

2 回答 2

0

您提到“使用大字符串需要很多时间”。

我建议你使用 Boyer Moore Horspool 算法。随着图案长度的增加,它变得更快。此外,使用子字符串剪切输入文本会导致性能不佳。相反,您可以添加一个参数来指定搜索的起点。

于 2013-07-02T01:52:44.880 回答
0

“KMP with Continuation”C++ 实现在这里,下面是:

#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;
}
于 2014-12-04T16:09:48.417 回答