字符串的查找KMP

基本思想,当出现不匹配的时候,就知晓一部分文本内容(因为在匹配失败前已经发生匹配)

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\n",ch+i);
     cout<<i<<endl;
    return 0;
}
View Code

 我不晓得看了多少次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;
}
View Code

 测试数据:

ABC ABCDA ABCDABCDABCDABDE
ABCDABD
View Code

 

posted @ 2019-03-06 17:47  Hello_World2020  阅读(135)  评论(0编辑  收藏  举报