KMP计数字符串出现次数

时间:2013-07-02 00:05:05

标签: algorithm knuth-morris-pratt

我已经实现了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);

              }
}

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

2 个答案:

答案 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;
}