KMP
采用部分匹配方式,每次扫描主串不必回溯,整个过程只扫描主串一遍,算法复杂度大大降低。
算法复杂度:O(n+m)
由于主串不必回溯,所以在匹配数据量大的文件使,不必放入缓存,可以边读取边进行模式匹配。
代码如下:
//Authors:xiaobei
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 100
#define OK 1
#define ERROR 0
typedef struct
{
char ch[MAXSIZE+1];
int length;
}SString; //定义串结构体
int Index_KMP(SString S,SString T,int pos,int nextval[]);
void get_nextval(SString T,int nextval[]); //get_next函数获得next[]数组
int main()
{
printf("这里是KMP算法!
");
int nextval[] = {0}; //定义next[]数组
int pos = 1,pos_i;
SString S,T;
printf("
请输入主串)>>>"); //输入主串,并获得主串长度,输出主串
gets(S.ch);
S.length = strlen(S.ch);
printf("
len_S:%d
",S.length);
puts(S.ch);
printf("
请输入要匹配子串)>>>"); //输入子串,并获得子串长度,输出子串
gets(T.ch);
T.length = strlen(T.ch);
printf("
len_T:%d
",T.length);
puts(T.ch);
get_nextval(T,nextval); //获得next
pos_i = Index_KMP(S,T,pos,nextval); //调用函数获得第一次匹配成功位置pos_i
printf("
匹配的起始位置为:%d",pos_i);
return 0;
}
int Index_KMP(SString S,SString T,int pos,int nextval[]) //串检索匹配函数
{
int i,j;
i = pos;
j = 1;
while(i<=S.length && j<=T.length) //当检索位置同时小于主串与子串时,执行循环
{
if(j == 0 || S.ch[i-1] == T.ch[j-1])
{
i++;
j++;
}
else
j = nextval[j];
}
if(j>T.length)
return i-T.length; //匹配成功
else
return 0; //匹配失败
}
//获得next[]数组的函数
void get_nextval(SString T,int nextval[])
{
int i,j;
i = 1;
nextval[1] = 0;
j = 0;
while(i<T.length)
{
if(j == 0 || T.ch[i] == T.ch[j])
{
i++;
j++;
if((T.ch[i]!=T.ch[j]))
nextval[i] = j;
else
nextval[i] = nextval[j];
}
else
j = nextval[j];
}
printf("--------------------
");
printf("输出next数组:
");
for(i = 0;i<T.length;i++)
printf("%d ",nextval[i]);
printf("
--------------------");
}
运行结果:
运行环境:
Dev-C++