KMP字符串匹配算法1
KMP字符串匹配算法1
KMP字符串匹配算法2
KMP字符串匹配算法2
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]来和 它对齐。
if(j==-1){
i++;
j++;
}
匹配成功一个,再去找下一个pattern[ ],j
的取值:
#include <iostream>
#include <cstring>
#include <stdlib.h>
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<n;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 <iostream>
#include <cstring>
#include <stdlib.h>
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;
}