KMP算法
使用场景:已知一个字符串S和一个模式串P,查找P在S中的位置?
字符串S: i指向当前字符
字符串P: j指向当前字符
暴力搜索
思路:逐个字符匹配即可。
问题:对于已知的情况会出现反复对比的操作,效率降低
KMP
思路:对模式串P进行分析,使得当S的一部分和P不匹配时,可以快速略过已知的不匹配的字符
做法:从模式串P中得到next数组,用next数组来表示如果当前字符(S[i] != P[j])不匹配,下一个P对应的j的位置, 而i只管一路向后i++
求next数组
理解方式:next其实也可以表示当前字符j之前的0 ~(j-1)位置的字符中,相同的前缀后缀的字符串的数量(长度)。这个数量其实就等于j下一个位置,因为P的索引以0开始。
(这样就说明如果此时j不匹配,但是我前面有一部分是和前缀相同的,就可以不重复匹配了!)
求取方式:使用递推的方式,即已知next[j],然后来求next[j+1],此时有两种情况了。
(next[j] = k:表示0~j-1中相同的前缀后缀,也是j位置不匹配时,下一个要对比的P的位置为k)
- 如果P[j+1] = P[k], 说明下一个要对比的位置是匹配的,所以往后移动一位即可next[j+1] = next[j]+1 = k+1;(如上图的abab到ababa字串,因为末尾的a和2位置的a相等,所以数量由2+1变为3)
- 如果P[j+1] != P[k],那么让k = next[k],即当跳转的(下一个要对比的)字符不匹配的时候,要继续往前跳转(下一个要匹配的字符串如果不匹配时的下一个要匹配的字符串……),直到匹配或者到起始点0(next[0] = -1)
private static void getNext(int[] next, String P){
int len = P.length();
int k = -1;
int j = 0;
next[0] = -1;//初始值,对应kj的初始值
while(j < len-1){
//k==-1即到头了,没有匹配的了,只好“重头再来”
if(k == -1 || P.charAt(j) == P.charAt(k)){
next[j+1