前缀表的定义:

next数组是用来表示前缀表的。前缀表是用来表示一个字符串中最大相等前后缀的表。
前缀:已第一个字符开头,并在当前下标之前结束的字符串
后缀:已当前下标字符结尾,并在当前下标之前开始的字符串
KMP算法可以加快字符串匹配的原因:比如下面的字符串如果是模式串—>匹配到a a b a a时匹配出错—>举例文本串为:a a b a c ……—> 那么模式串当前不匹配字符下标-1对应的前缀表不为0时,文本串中c之前的字符一定有与模式串开头的字符相对应的—>只需要从模式串不匹配字符下标-1对应的前缀表的下标的字符开始比较(写的有点绕—>就是接着比较模式串str[1]与c是否对应)
Eg: a a b a a f
前缀表:0 1 0 1 2 0
next数组有两种表示方法:一种是next数组为前缀表元素-1,另一种是next数组就等于前缀表的情况。这两种情况本质上是一样的,只是代码实现略有不同:

next数组为前缀表元素-1代码:

  1. #include<iostream>
  2. #include<string>
  3. using namespace std;
  4. //next数组等于前缀表-1的情况
  5. void getNext(int* next, const string& str2) {
  6. int j = -1;
  7. next[0] = -1;
  8. int size = str2.size();
  9. for (int i = 1; i < size; i++) {
  10. while (j > -1 && next[i] != next[j + 1]) {
  11. j = next[j];
  12. }
  13. if (str2[i] == str2[j + 1]) {
  14. j++;
  15. }
  16. next[i] = j;
  17. }
  18. }
  19. int KMP(const string& str1, const string& str2) {
  20. int Psize = str2.size();
  21. int* next = (int *)malloc(Psize * sizeof(int));
  22. getNext(next, str2);
  23. int j = -1;
  24. for (int i = 0; i < str1.size(); i++) {
  25. while (j > -1 && str1[i] != str2[j + 1]) {
  26. j = next[j];
  27. }
  28. if (str1[i] == str2[j + 1]) {
  29. j++;
  30. }
  31. if (j == Psize - 1)
  32. return i - j;
  33. }
  34. return -1;
  35. }
  36. int main() {
  37. string str1("ababcabccabcacbab");
  38. string str2("abcac");
  39. int res = KMP(str1, str2);
  40. cout << res << endl;
  41. return 0;
  42. }

next数组等于前缀表的情况:

  1. #include<iostream>
  2. #include<string>
  3. using namespace std;
  4. //next数组等于前缀表的情况
  5. void getNext(int* next, const string& str2) {
  6. int j = 0;
  7. next[0] = 0;
  8. int size = str2.size();
  9. for (int i = 1; i < size; i++) {
  10. while (j > 0 && next[i] != next[j]) {
  11. j = next[j - 1];
  12. }
  13. if (str2[i] == str2[j]) {
  14. j++;
  15. }
  16. next[i] = j;
  17. }
  18. }
  19. int KMP(const string& str1, const string& str2) {
  20. int Psize = str2.size();
  21. int* next = (int *)malloc(Psize * sizeof(int));
  22. getNext(next, str2);
  23. int j = 0;
  24. for (int i = 0; i < str1.size(); i++) {
  25. while (j > 0 && str1[i] != str2[j]) {
  26. j = next[j - 1];
  27. }
  28. if (str1[i] == str2[j]) {
  29. j++;
  30. }
  31. if (j == Psize)
  32. return i - j + 1;
  33. }
  34. return -1;
  35. }
  36. int main() {
  37. string str1("ababcabccabcacbab");
  38. string str2("abcac");
  39. int res = KMP(str1, str2);
  40. cout << res << endl;
  41. return 0;
  42. }