kmp(含水分)

KMP字符串匹配算法1


KMP字符串匹配算法1

KMP字符串匹配算法2


KMP字符串匹配算法2

kmp(含水分)_第1张图片

prefix[0] = 0;
0 AB
1 ABA
2 ABAB
0 ABABC
1 ABABCA
2 ABABCAB
3 ABABCABA
1 ABABCABAA

如果下个位置相等就

if(p[len]==p[i])
len++
prefix[i] = len;
void prefix_table(char pattern[],int prefix[],int n){
   prefix[0] = 0;
   int len = 0;
   int i = 1;
   while (i<n){
       printf("i=%d len=%d\n",i,len);
       //相等
       if(pattern[i] == pattern[len]){
           len++;
           prefix[i]=len;
           i++;
       }
       //不相等
       else{
           if(len>0)
                len = prefix[len-1];
           else {
               prefix[i] = 0;//此时len = 0;
               i++;
           }
       }
   }
}

中途的元素不匹配用p[-1]来和 它对齐。
kmp(含水分)_第2张图片

if(j==-1){
     i++;
     j++;
}

匹配成功一个,再去找下一个pattern[ ],j的取值:

kmp(含水分)_第3张图片

#include 
#include 
#include 
using namespace std;
void move_prefix_table(int prefix[],int n){
    int i;
    for(i=n-1;i>0;i--){
        prefix[i] = prefix[i-1];
    }
    prefix[0] = -1;
}
void prefix_table(char pattern[],int prefix[],int n){
   prefix[0] = 0;
   int len = 0;
   int i = 1;
   while (i<n){
       printf("i=%d len=%d\n",i,len);
       //相等
       if(pattern[i] == pattern[len]){
           len++;
           prefix[i]=len;
           i++;
       }
       //不相等
       else{
           if(len>0)
                len = prefix[len-1];
           else {
               prefix[i] = 0;//此时len = 0;
               i++;
           }
       }
   }
}
void kmp_search(char text[],char pattern[]){
    int n=strlen(pattern);
    int* prefix = (int*)malloc(sizeof(int)*n);
    prefix_table(pattern,prefix,n);
    move_prefix_table(prefix,n);
    //text[i] len(text) = m
    //pattern[j] len(pattern) = n;
    int i = 0;
    int m =strlen(text);
    int j = 0;
    while(i<m){
        if(j==n-1 && text[i] == pattern[j]){
            printf("Find pattern at %d.\n",i-j);
            j = prefix[j];
        }
        if(text[i]==pattern[j]){
            i++;
            j++;
        } else{
            j = prefix[j];
            if(j==-1){
                i++;
                j++;
            }
        }
    }
}
int main(){
//    char pattern[] = "ABABCABAA";
//    int prefix[9];
//    int n=9;
//    prefix_table(pattern,prefix,n);
//    move_prefix_table(prefix,n);
//    int i;
//    for(int i=0;i
//        printf("%d ",prefix[i]);
//    }
    char pattern[] = "ABABCABAA";
    char text[] = "ABABABCABAABABABABABCABAA";
    kmp_search(text,pattern);
    return 0;
}

此后不用看
但是问题是本应该是和p[1]来对齐这个地方,但是上面用p[3]来对齐,我们发现p[3]->p[1]->p[0],我们发现p[3]->p[1],解决办法就是我觉得可以prefix数组多增加一位,然后用p[3]来对齐这个。
这个prefix数组多加了prefix【0】=-1,会把最后一位给抹除掉,可以申请prefix为n+1位。这样的话,当找到一个匹配的字符串之后,再去找下一个匹配字符串的时候,j = prefix【j+1】(相对原先的j = prefix【j】)效率高一点。

#include 
#include 
#include 
using namespace std;
void move_prefix_table(int prefix[],int n){
    int i;
    for(i=n-1;i>0;i--){
        prefix[i] = prefix[i-1];
    }
    prefix[0] = -1;
}
void prefix_table(char pattern[],int prefix[],int n){
   prefix[0] = 0;
   int len = 0;
   int i = 1;
   n = n-1;
   while (i<n){
       printf("i=%d len=%d\n",i,len);
       //相等
       if(pattern[i] == pattern[len]){
           len++;
           prefix[i]=len;
           i++;
       }
       //不相等
       else{
           if(len>0)
                len = prefix[len-1];
           else {
               prefix[i] = 0;//此时len = 0;
               i++;
           }
       }
   }
}
void kmp_search(char text[],char pattern[]){
    int n=strlen(pattern);
    int* prefix = (int*)malloc(sizeof(int)*(n+1));
    prefix_table(pattern,prefix,n+1);
    move_prefix_table(prefix,n);
    //text[i] len(text) = m
    //pattern[j] len(pattern) = n;
    int i = 0;
    int m =strlen(text);
    int j = 0;
    while(i<m){
        if(j==n-1 && text[i] == pattern[j]){
            printf("Find pattern at %d.\n",i-j);
            j = prefix[j+1];
        }
        if(text[i]==pattern[j]){
            i++;
            j++;
        } else{
            j = prefix[j];
            if(j==-1){
                i++;
                j++;
            }
        }
    }
}
int main(){
    char pattern[] = "ABABCABAA";
    char text[] = "ABABABCABAABABABABABCABAA";
    kmp_search(text,pattern);
    return 0;
}

你可能感兴趣的:(数据结构)