一、BF算法(朴素算法)
缺点:每次失配都是从头重新开始,效率低下
#include <stdio.h>
#include <string.h>
int main()
{
char s[]="abcdefgab";
char t[]="abcdef";
int a,b;
int i=0,j=0;
a=strlen(s);
b=strlen(t);
j=0;
printf(" 请输入数i,代表从主串s哪个位置开始\n");
scanf("%d",&i);
while(j<b&&i<a)
{
if(s[i]==t[j])
{
i++;
j++;
}
else
{
i=i-j+2;
j=1;
}
}
if(j>=b)
printf("匹配成功");
else
printf("匹配失败");
return 0;
}
//0 匹配成功
//其他数 匹配失败
二、kmp算法(效率高)
1.KMP算法的关键在于使用next数组
2.next数组作用:当模式匹配串T(子串)失配时,next数组对应的元素指导应该用T串哪个元素进行下一轮的匹配(就是失配时,后缀的next值所对应的位置的next的值当做下一轮匹配的位置)
三、前后缀怎么看
1.若子串是 a,b,a,c
在c处失配,看第一个和c的前一位=>相同都是a
(一位相同则c的next为2=>用自己2号去与目标串匹配)
2.若子串是 a,b,a,b,a,c
在c处失配,最前面三位和除c的后三位相同
(三位相同,c的next为4=>用自己的4号位与目标串匹配)
3.若在1号位就失配
next=0 =>自己的0号去配
四、得到next功能函数
//前缀是固定的,后缀是相对的
void o_next(String T,int *next)//o_next函数里只需要子串T,建立指针next是为了传数组next
{
int j=0;//j是前缀
int i=1;//i是后缀
next[1]=0;//这是恒定的
while(i<T.length)
{
if(0==j||T.str[i]==T.str[j])//o==j是刚开始让它进入用的
{
i++;
j++;
next[i]=j;
}
else
{
j=next[j];//next的作用,告诉这一次到哪一位置去匹配
}
}
}
五、KMP算法源码
/************************************************************************* > File Name: kmp.c > Author: geeker > Mail: 932834897@qq.com > Created Time: 2017年02月23日 星期四 14时11分34秒 ************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct
{
int length;//存字符串长度
char *str;//存字符串
}String;//若无法理解String的在前面的博客有解释
//前缀是固定的,后缀是相对的
void o_next(String T,int *next)
{
int j=0;//j是前缀
int i=1;//i是后缀
next[1]=0;//这是恒定的
while(i<T.length)
{
if(0==j||T.str[i]==T.str[j])//o==j是刚开始让它进入用的
{
i++;
j++;
next[i]=j;
}
else
{
j=next[j];//next的作用,告诉这一次到哪一位置去匹配
}
}
}
//kmp函数最后返回子串T在主串S第pos个字符的位置
//若不存在,返回0
int kmp(String S,String T,int pos)//pos是需要从哪里开始寻找的位置
{
int i=pos;//开始索引的位置
int j=1;
int next[255];//最多存放255
o_next(T,next);//模式匹配串不用去管S串是怎么样的
while(i<=S.length&&j<=T.length)//条件,前后缀都要小于字符串长度
{
if(0==j||S.str[i]==T.str[j])//必须要0==j,否则会出现next引用越界,也是为了让第一下能进去
{
i++;
j++;
}
else
{
j=next[j];
}
}
if(j>T.length)//匹配成功,返回匹配的位置
{
return i-T.length;
}
else
{
return 0;
}
}
int main()
{
String S,T;
char *str=" ababaaaba";
S.str=str;//主字符串的赋值
S.length=strlen(str)-1;//排除串前的空格符 ???
char *str1=" baa";
T.str=str1;//子字符串的赋值
T.length=strlen(str1)-1;
int k;
k=kmp(S,T,0);//传入S,T字符串,并从0开始匹配
if(0==k)
{
printf("匹配失败\n");
}
else
{
printf("匹配成功了,匹配点为%d\n",k);
}
//最后显示S串中next数组里的值
int next[255];
o_next(S,next);
printf("S=ababaaaba,T=baa的next数组为:\n");
for(int i=1;i<=S.length;i++)
{
printf("%d ",next[i]);
}
printf("\n");
return 0;
}
效果图