你好陌生人,请不要试图越过权限文章,谢谢!

KMP算法的心得

前言

  KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-Morria-Pratt 算法,简称 KMP 算法。该算法相对于 Brute-Force(暴力)算法有比较大的改进,主要是消除了主串指针的回溯,从而使算法效率有了某种程度的提高。

  然后,坑啊,KMP这东西我看了一天才给我整明白一点,现在还有点恍惚,我心态差点崩了,呜呜

代码

  KMP算法的核心部分主要是或者模式串的前缀,什么意思呢,就是比如:abcabf 那么,对应的他们的前缀表next是[0,0,0,0,1,2]。

  比较抽象,可以把他看做这个字符串给它两个指针 j、k 分别对应他们前缀和后缀,然后一一比对,找到他们的最大公共字符串,很离谱吧。 而像这样的 第一位、第二位一般都是0,因为他们前后都不一样嘛

  我的理解就是:

1
2
3
4
5
6
7
8
9
10
abcabf
abcabf

看这两个,错开了,两个错开比对,第一个是后缀,相对应的第一个位置不要了
第二个就是前缀了
首先是 b跟a比,不同,则 0
c跟b比 0
以此类推

KMP最核心的就是求next了,而最长的公共 就是 下面前缀的长度了,如果不相同,把对应的next位置的写入前缀公共长
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static int[] getNext(String ps) {

char[] p = ps.toCharArray();

int[] next = new int[p.length];
next[0] = -1;
int j = 0;
int k = -1;

while (j<p.length -1){
if(k == -1 || p[j] == p[k]){
j++;
k++;
next[j] = k;
}else {
k = next[k];
}
}
return next;

}

  KMP的主函数就太简单了,作为暴力美学的延伸,有了next前缀表,那么J就不必回溯,就直接让j对应前缀表值返回继续,主要代码是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static int kmp(String ts,String ps){

char[] t = ts.toCharArray();
char[] p = ps.toCharArray();

int[] next = getNext(ps);

int i = 0;
int j = 0;

while (i<t.length && j<p.length){
if(j == -1 || t[i] == p[j]){
i++;
j++;
}else{
j = next[j];
}
}

if(j == p.length){
return i-j;
}else {
return -1;
}



}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public class KMP {

public static void main(String[] args){

String ts = "abcabcabf";
String ps = "abcabf";
int begin_place = kmp(ts,ps);

System.out.println(begin_place);




}



public static int kmp(String ts,String ps){

char[] t = ts.toCharArray();
char[] p = ps.toCharArray();

int[] next = getNext(ps);

int i = 0;
int j = 0;

while (i<t.length && j<p.length){
if(j == -1 || t[i] == p[j]){
i++;
j++;
}else{
j = next[j];
}
}

if(j == p.length){
return i-j;
}else {
return -1;
}



}

public static int[] getNext(String ps) {

char[] p = ps.toCharArray();

int[] next = new int[p.length];
next[0] = -1;
int j = 0;
int k = -1;

while (j<p.length -1){
if(k == -1 || p[j] == p[k]){
j++;
k++;
next[j] = k;
}else {
k = next[k];
}
}
return next;

}

}

结尾

  KMP算法让我头疼,让我死吧。膜拜发明此算法的大佬,到底是怎么想到的,我爱了。