著名的字符串匹配算法——KMP算法。
主要分为构造“部分匹配表”,和利用部分匹配表进行匹配两部分,下面代码比较简洁易懂。
//KMP算法,构造部分匹配表
#include <cstring>
#include <iostream>
using namespace std;
//朴素匹配,时间复杂度O(m*n)
int plain_Match(char* T,char* P)
{
int m = strlen(P),n = strlen(T),j;
for(int i = 0;i < n-m;i++){
for(j = 0;j < m;j++)
if(P[j] != T[i+j]) break;
if(j == m) return i;
}
return -1;
}
//构造"部分匹配表"
int makeNext(char *P,int *next)
{
int m = strlen(P),cnt = 0; //cnt记录已匹配的字符数
next[0] = 0;
for(int i = 1;i < m;i++){
P[cnt] == P[i] ? cnt++ : cnt = 0;
next[i]=cnt;
}
}
int kmp(char* T,char* P,int* next)
{
int n = strlen(T), m = strlen(P),cnt = 0;
for(int i = 0;i < n;i++){
while(cnt > 0 && P[cnt] != T[i]) cnt = next[cnt-1];
if(P[cnt] == T[i]) cnt++;
if(cnt == m) return i-m+1;
}
return -1;
}
void printL(int *arr,int n)
{
for(int i = 0;i < n;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
int main()
{
const int maxn = 40;
// char P[] = "aacaadaacaad",T[] = "aacabaacaadaacaadabaacaadaadaac";
char P[] = "ABCDABD",T[] = "BBC ABCDAB ABCDABCDABDE";
cout<<"朴素匹配: "<<plain_Match(T,P)<<endl;
int next[maxn]={0};
makeNext(P,next);
cout<<"部分匹配表: ";printL(next,maxn);
cout<<"KMP匹配: "<<kmp(T,P,next);
return 0;
}