[关闭]
@zsh-o 2018-07-14T12:30:12.000000Z 字数 1539 阅读 789

KMP

算法


KMPnext数组表示的是 当前字符匹配失败,应该跳转到模式串中哪个位置继续进行匹配,其本质思想是找到模式串当前位置的子串的前缀子串和后缀子串相同的最大长度,这样匹配到当前位置不同时,原串中该位置前面个字符仍与模式串中的前个字符相同,故只需从继续匹配即可

image.png-5.5kB

这是当前位置所表示的情况,此时,next[i] = j,由于下标从0开始所以此时的相同串为红色部分并且长度为,表示当i位置不同时需要继续匹配j位置的字符,那么需要分为两种情况:

故生成next数组的代码为

  1. int* get_next(char* A, int size_a){
  2. int* next = new int[size_a];
  3. A[0] = -1;
  4. A[1] = 0;
  5. int i = 0, j = 0;
  6. while(i < size_a){
  7. j = next[i - 1];
  8. while(j >= 0 && A[i-1] != A[j]){
  9. j = next[j];
  10. }
  11. next[i] = j + 1;
  12. i++;
  13. }
  14. return next;
  15. }

匹配的代码与生成next数组的代码很相似,也很简单,这里返回第一次匹配成功的位置,没有则返回-1

  1. int kmp_search(char* S, int size_s, char* A, int size_a, int* next){
  2. int index = -1;
  3. int i = 0, j = 0;
  4. while(i < size_s){
  5. while(j >= 0 && S[i] != A[j]){
  6. j = next[j];
  7. }
  8. j++;
  9. i++;
  10. if(j == size_a){
  11. index = i - j;
  12. break;
  13. }
  14. }
  15. return index;
  16. }

这里有一点需要注意,以前需要的一个题,用kmp寻找模式串在原串中出现的次数,这时next数组只需要添加最后一位匹配成功后应该转移的位置即可,只需要修改匹配完成部分的代码即可

  1. int* get_next_statistic(char* A, int size_a){
  2. int* next = new int[size_a + 1]; // *
  3. A[0] = -1;
  4. A[1] = 0;
  5. int i = 0, j = 0;
  6. while(i <= size_a){ // *
  7. j = next[i - 1];
  8. while(j >= 0 && A[i-1] != A[j]){
  9. j = next[j];
  10. }
  11. next[i] = j + 1;
  12. i++;
  13. }
  14. return next;
  15. }
  16. int kmp_search_statistic(char* S, int size_s, char* A, int size_a, int* next){
  17. int r = 0;
  18. int i = 0, j = 0;
  19. while(i < size_s){
  20. while(j >= 0 && S[i] != A[j]){
  21. j = next[j];
  22. }
  23. j++;
  24. i++;
  25. if(j == size_a){
  26. r++;
  27. j = next[j];
  28. }
  29. }
  30. return r;
  31. }

结果:

  1. int main(){
  2. char* S = "abababaabcacabaabcacab";
  3. char* A = "abaabcacab";
  4. printf("%d\n",kmp_search(S, strlen(S), A, strlen(A), get_next(A, strlen(A))));
  5. printf("%d\n",kmp_statistic(S, strlen(S), A, strlen(A), get_next_statistic(A, strlen(A))));
  6. }

  1. 4
  2. 2
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注