1. 程式人生 > >[牛客算法系列] KMP演算法

[牛客算法系列] KMP演算法

題目

  • 給定兩個字串source 和 match, 長度分別為 N 和 M。實現一個演算法,如果字串source 中,含有子串match, 則返回match 在 source 中的開始為位置,不含有返回-1.
  • 舉例
    source = “acbc”, match = “bc” , 返回2.
    source = “acbc”, match = “bcc” , 返回-1;
  • 要求,如果match 的長度大於source 的長度(M > N)source 必然不會含有match, 可直接返回-1。但如果N >= M ,要求時間複雜度為O(N).

分析程式碼

  • 最普通的解法是從左到右遍歷source 的每個字元,然後看如果以當前字元作為第一個字元出發是否匹配出match。時間複雜度較高O(N * M)。
  • 本文KMP解法能夠做到時間複雜度O(N)
  • 主要是生成match字串的nextArr 陣列,這個陣列的長度與match字串的長度一樣,nextArr[i]的含義是在match[i]之前的字串match[0…i-1] 中,必須以match[i-1]結尾的字尾子串(不能含有match[0])與必須以match[0]開頭的字首子串(不能含有match[i - 1])最大的匹配長度是多少。這個長度是nextArr[i]的值。

程式碼

// kmp

public int[] getNextArray(char[] ms){
	if(ms.length == 1){
		return new int[]{-1}
; } int[] next = new int[ms.length]; next[0] = -1; next[1] = 0; int pos = 2; int cn = 0; while(pos < next.length){ if(ms[pos - 1] == ms[cn]){ next[pos++] == ++cn; }else if(cn > 0){ cn = next[cn]; }else{ next[pos++] = 0; } } return next; } pubulic int kmp(String source, String match)
{ int i = 0, j = 0; char[] src = source.toCharArray(); char[] mat = match.toCharArray(); int sLen = src.length; int mLen = mat.length; int[] next = getNextArray(mat); while(i < sLen && j < mLen){ //如果j = -1 ,或者當前字元匹配成功(src[i] = mat[j]), 都讓i++,j++ if(j == -1 || src[i] == mat[j]){ i++; j++; }else{ //如果j!= -1 且當前字元匹配失敗,則令i 不變, j = next[j] ,即讓match 串 右移 j- next[j] 個單位 j = next[j]; //此處體現next 陣列的作用, source 陣列無需退回。 } } if(j == mLen) return i - j; return -1; }