基本思想,当出现不匹配的时候,就知晓一部分文本内容(因为在匹配失败前已经发生匹配)
P[0 ~ k-1] == P[j-k ~ j-1]
//KMP #include<iostream> #include<string.h> #include<malloc.h> using namespace std; void come(string pattern,int next[]){ int i=1; int j=-1; const int m=pattern.length(); next[0]=j;//第一个为0 for(int i=1;i<m;i++){ while(j>-1&&pattern[j+1]!=pattern[i]) j=next[j]; //恢复0 恢复的地方 if(pattern[i]==pattern[j+1]) j++; next[i]=j; } } /*void com(const char *pattern,int next[]){ //当匹配后跳转的地方next[i]----->pattern[j] int i=1; int j=-1; const int m=strlen(pattern); next[0]=j;//第一个为0 for(int i=1;i<m;i++){ while(j>-1&&pattern[j+1]!=pattern[i]) j=next[j]; //恢复0 恢复的地方 if(pattern[i]==pattern[j+1]) j++; next[i]=j; } } */ /*int kmp(const char *text,const char *pattern){ int i; int j=-1; const int n=strlen(text); const int m=strlen(pattern); if(n==0&&m==0) return 0; if(m==0) return 0; int *next=(int*)malloc(sizeof(int)*m); com(pattern,next); for(i=0;i<n;i++) { while(j>-1&&pattern[j+1]!=text[i]) j=next[j]; if(text[i]==pattern[j+1]) j++; if(j==m-1) { free(next); return i-j; } } free(next); return -1; }*/ int Kmp(string text,string pattern){ int i; int j=-1; const int n=text.length(); const int m=pattern.length(); if(n==0&&m==0) return 0; if(m==0) return 0; int next[m]; come(pattern,next); for(i=0;i<n;i++) { while(j>-1&&pattern[j+1]!=text[i]) j=next[j]; if(text[i]==pattern[j+1]) j++; if(j==m-1) { // free(next); return i-j; } } // free(next); return -1; } int main() { // char text[]="ABC ABCDA ABCDABCDABCDABDE"; // char pattern[]="ABCDABD"; // char *ch=text; string text="ABC ABCDA ABCDABCDABCDABDE"; string pattern="ABCDABD"; int i=Kmp(text,pattern); // if(i>=0) printf("%s ",ch+i); cout<<i<<endl; return 0; }
我不晓得看了多少次kmp算法了,感觉还是要写博客,不然的话算法这个东西,太容易忘记了。。。
分析:
文本字符串长度为n,模式串长度为m,创建数组next[0...m-1],做一个标记,是对自身的标记
//KMP #include<iostream> #include<string.h> #include<malloc.h> using namespace std; void come(string pattern,int next[]){ int i=1; int j=-1; const int m=pattern.length(); next[0]=j;//第一个为-1 0-(-1)==1 转移1 for(int i=1;i<m;i++){ while(j>-1&&pattern[j+1]!=pattern[i]) j=next[j]; //恢复0 恢复的地方 if(pattern[i]==pattern[j+1]) j++; next[i]=j; } } int Kmp(string text,string pattern){ int i; int j=-1; const int n=text.length(); const int m=pattern.length(); if(n==0&&m==0) return 0; if(m==0) return 0; int next[m]; come(pattern,next); for(i=0;i<n;i++) { if(j>-1&&pattern[j+1]!=text[i]) j=next[j]; if(text[i]==pattern[j+1]) j++; if(j==m-1) return i-j; } return -1; } int main() { string text="ABC ABCDA ABCDABCDABCDABDE"; string pattern="ABCDABD"; int i=Kmp(text,pattern); cout<<i<<endl; return 0; }
测试数据:
ABC ABCDA ABCDABCDABCDABDE
ABCDABD