Java獲取指定字符串在另一個字符串中的出現次數

百度發現很多答案都是錯誤的,全是相互抄襲,也不經過驗證就放出來,這裏提供正確的搜索算法。

方案一,使用KMP算法,KMP算法是一種改進的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人們稱它爲克努特莫里斯普拉特操作(簡稱KMP算法)。KMP算法的核心是利用匹配失敗後的信息,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是通過一個next()函數實現,函數本身包含了模式串的局部匹配信息。KMP算法的時間複雜度O(m+n)。

代碼實現:

public class KMPSearcher {


  public static int KMPSearch(String pat, String txt) {
    int M = pat.length();
    int N = txt.length();

    // create lps[] that will hold the longest
    // prefix suffix values for pattern
    int lps[] = new int[M];
    int j = 0;  // index for pat[]

    // Preprocess the pattern (calculate lps[]
    // array)
    computeLPSArray(pat, M, lps);

    int i = 0;  // index for txt[]
    int res = 0;
    int next_i = 0;

    while (i < N) {
      if (pat.charAt(j) == txt.charAt(i)) {
        j++;
        i++;
      }
      if (j == M) {
        // When we find pattern first time,
        // we iterate again to check if there
        // exists more pattern
        j = lps[j - 1];
        res++;

        // We start i to check for more than once
        // appearance of pattern, we will reset i
        // to previous start+1
        if (lps[j] != 0) {
          i = ++next_i;
        }
        j = 0;
      }

      // mismatch after j matches
      else if (i < N && pat.charAt(j) != txt.charAt(i)) {
        // Do not match lps[0..lps[j-1]] characters,
        // they will match anyway
        if (j != 0) {
          j = lps[j - 1];
        } else {
          i = i + 1;
        }
      }
    }
    return res;
  }

  private static void computeLPSArray(String pat, int M, int lps[]) {
    // length of the previous longest prefix suffix
    int len = 0;
    int i = 1;
    lps[0] = 0;  // lps[0] is always 0

    // the loop calculates lps[i] for i = 1 to M-1
    while (i < M) {
      if (pat.charAt(i) == pat.charAt(len)) {
        len++;
        lps[i] = len;
        i++;
      } else  // (pat[i] != pat[len])
      {
        // This is tricky. Consider the example.
        // AAACAAAA and i = 7. The idea is similar
        // to search step.
        if (len != 0) {
          len = lps[len - 1];

          // Also, note that we do not increment
          // i here
        } else  // if (len == 0)
        {
          lps[i] = len;
          i++;
        }
      }
    }
  }
}

方案二,字符串從左到右逐一匹配

public class StringCounter {

  public static int countFreq(String pat, String txt) {
    int M = pat.length();
    int N = txt.length();
    int res = 0;

    /* A loop to slide pat[] one by one */
    for (int i = 0; i <= N - M; i++) {
            /* For current index i, check for
        pattern match */
      int j;
      for (j = 0; j < M; j++) {
        if (txt.charAt(i + j) != pat.charAt(j)) {
          break;
        }
      }

      // if pat[0...M-1] = txt[i, i+1, ...i+M-1]
      if (j == M) {
        res++;
        j = 0;
      }
    }
    return res;
  }
}

測試結果:

    int count = KMPSearcher.KMPSearch("aa", "aaaa");
    System.out.println(count);

    int count1 = StringCounter.countFreq("aa", "aaaa");
    System.out.println(count1);

均輸出 3 。

參考文檔:https://www.geeksforgeeks.org/frequency-substring-string/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章