重温数据结构之字符串匹配(Kmp)

313 阅读3分钟

1. 字串返回在主串的第pos个字符之后的位置(普通版)

function findIndex(S,T,pos){
  let i  = pos;
  let j = 0;
  while (i < S.length && j< T.length) {
    // statement
    if(S[i] === T[j]){
    	i++;
    	j++;
    }else{
    	i = i-j+1;
    	j = 0;
    }
  }
  if(j >= T.length) {
  	return i - T.length;
  }else{
  	return 0;
  }
}
console.log(findIndex("ssssdddssabcdefgab","abcdef",0));

下面这段话是摘自程杰老师的《大话数据结构》里面的。以前上学那会儿课本是严蔚敏老师的《数据结构c语言版》与我们自己老师出版的数据结构,闲来无事重新对比这几本书看一下。

分析一下, 最好的情况是什么?那就是一开始就区配成功,比如 "googlegood" 中去找 googlen ,时间复杂度为 O(1)。 稍差一些,如果像刚才例子中第二、 三、四位 一样,每次都是首字母就不匹配,那么对 T 串的循环就不必进行了,比如 "abcdefgoogle" 中去找 google。 那么时间复杂度为 O(n+m) , 其中 n 为主串长度, m 为要匹配的子串长度。根据等概率原则,平均是 (n+m) /2 次查找,时间复杂度为 O(n+m).

那么最坏的情况又是什么?就是每次不成功的匹配都发生在串 T 的最后一个字 符。举一个很极端的例子。主串为 s= "000000000000000000000000000000000000 00000000000001" ,而要匹配的子串为 T= "0000000001" ,前者是有 49 个 "0" 和 1 个 "I n 的主串,后者是 9 个 "0" 和 1 个 U1" 的子串。在匹配时,每次都得将 τ 中字符循环到最后一位才发现:哦,原来它们是不匹配的。 这样等于 T 审需要在 S 串 的前 40 个位置都需要判断 10 次,并得出不匹配的结论,

直到最后第 41 个位置,因为全部匹配相等,所以不需要再继续进行下去, 如果最终投有可匹配的子串, 比如是 T= "0000000002 n ,到了第 41 位 置判断不匹配后同样不需要继续比对下去。 因此最坏情况的时间复杂度为 O((n- m+1)*m)。

在实际运用中,对于计算机来说,处理的都是二进 位的 0 和 1 的靡,一个字符的 ASCII 码也可以看成是 8 位的二进位 01 串,当然,汉 字等所有的字符也都可以看成是多个 0 和 1 串。再比如像计算机图形也可以理解为是 由许许多多个 0 和 1 的串组成。所以在计算机的运算当中,模式匹配操作可说是随处 可见,而刚才的这个算法,就显得太低效了。

2.字串返回在主串的第pos个字符之后的位置(kmp版)

	//构造KMP的next数组
function get_nextval(T,nextval){
    let i,j;
    let arr = nextval;
    i = 0;
    j = -1;
    arr[0] = -1
    while(i < T.length){
	if(j == -1 || T[i] == T[j]){
	    ++i;
	    ++j;
	    arr[i] = j;
	}else{
	    j = arr[j]
	    }
	}
	    return arr;
	}
	//查找算法
	function Index_KMP(S,T){
	    let i = 0;
	    let j = 0;
	    let arr = new Array(255);
	    let nextArr = get_nextval(T,arr);
	    while(i < S.length && j < T.length){
	        if(j == -1 || S[i] == T[j]){
	            ++i;
	            ++j;
	        }else{
	            console.log(i)
	            j = nextArr[j]
	        }
	       }
            if(j >= T.length){
	        return i - T.length;
	        }else{
	        return 0;
	        }
	}

	console.log(Index_KMP("ssssdddssabcdefgab","abcdef"));

总结:看书一定要自己写一遍,他们写的也有好多问题的。一定要谨慎