暴力匹配算法和KMP 算法比较:
算法实现:
#include<iostream>
#include<stdio.h>
#include<fstream>//使用fstream中定义的类及各种成员函数
#include<string.h>
#include<stdlib.h>
#include<time.h> //时间函数
using namespace std; //开辟内存空间
int strStr(char* haystack,char* needle) //暴力算法
{
if(haystack==NULL||needle==NULL)//判断主串和副串是否为空
return-1;
const int len_h=strlen(haystack);//求主串的长度
const int len_n=strlen(needle);
for(int i=0;i<len_h-len_n+1;i++) //长度小于副串一定找不到
{
int j=0;
for(j=0;j<len_n;j++)
{
if(haystack[i+j]!=needle[j]) //每个字符比较
{
break;
}
}
if(j==len_n)
returni;
}
return-1;
}
void cal_next(char* source,int* next,intlen)//求next的函数(KMP)
{
next[0]=-1; //next[0]初始化为-1,-1表示不存在相同的最大前缀和最大后缀
int k=-1; //k初始化为-1
for(int q=1;q <= len-1; q++)
{
while (k > -1 && source[k + 1] != source[q])
//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
{
k = next[k]; //往前回溯
}
if (source[k + 1] == source[q])//如果相同,k++
{
k = k + 1;
}
next[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
}
}
int KMP(char *source, int slen, char*target, int plen)
{
int *next = new int[plen];
cal_next(target, next, plen);//计算next数组
int k = -1;
for (int i = 0; i < slen; i++)
{
while (k >-1&& target[k + 1] != source[i])
//target和source不匹配,且k>-1(表示target和source有部分匹配)
k = next[k]; //往前回溯
if (target[k + 1] == source[i])
k = k + 1;
if (k == plen-1) //说明k移动到target的最末端
{
return i-plen+1; //返回相应的位置
}
}
return -1;
}
int main()//主函数入口
{
fstreamoutfile;
outfile.open(“f3.txt”,ios::out);//以写的方式打开文件
if(!outfile)//判断文件是否为空
{
cout<<“f3.txtcan’t open.\n”;
abort();
}
//生成随机数
inti;
srand((unsigned)time(NULL));//它初始化随机种子,会提供一个种子,这个种子会对应一个随机数,如果使用相同的种子后面的rand()函数会出现一样的随机数
for(i=0;i<10000;i++){
char ch=rand()%26+’a’;//产生a到z的小写字母
outfile<<ch;//写进文件
}
fstreaminfile;
infile.open(“f3.txt”,ios::in);//读文件
if(!infile){
cout<<“f3.txtcan’t open.\n”;
abort();
}
chars1[10000];
while(!infile.eof())//一直读字符,直到读到完
{
infile.getline(s1,sizeof(s1));
}
infile.close();//关闭文件
char *source=s1;
char * target=”ab”;
cout<<“主串是:”<<source<<endl; //主串
cout<<“要查找的字符串是:”<<target<<endl;//副串
int i1=strlen(source);//求字符串长度
int j1=strlen(target);
clock_tstart,finish;//时间函数
doubletotaltime;
start=clock();
inta = KMP(source,i1, target,j1);//传参函数调用
for(intd=0;d<10000000;d++){KMP(source,i1, target,j1);}
if(a==-1)
cout<<“字符串不匹配“<<endl;
else
cout<<“从第“<<a<<“个字符开始匹配“<<endl;
finish=clock();
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
cout<<“kmp程序的运行时间为“<<totaltime<<“ s”<<endl;//1
clock_tstart1,finish1;//时间结束
doubletotaltime1;
start1=clock();
int b;
b=strStr(source,target);
for(intc=0;c<10000000;c++){strStr(source,target);}
if(b==-1)
cout<<“字符串不匹配“<<endl;
else
cout<<“从第“<<b<<“个字符开始匹配“<<endl;
finish1=clock();
totaltime1=(double)(finish1-start1)/CLOCKS_PER_SEC;
cout<<“暴力程序的运行时间为“<<totaltime1<<“秒!”<<endl;//2
return0;
}
输出结果:
两个算法比较分析:
经计算,暴力匹配算法易知其时间复杂度:o(n-m)*m,而KMP 算法时间复杂度为: o(n+m),两种算法同时在C++同一个编译器下多次执行,首先从运行结果和时间复杂度上,KMP算法都比暴力算法好很多,暴力匹配算法虽然能解决问题,但是在效率上差的很远,暴力匹配算法无论是在代码量还是在处理问题上,都没有KMP算法高效, KMP算法的精髓在于不必要以主串种每一个元素下标为首都比一边,而是建立了next,以巧妙地算法跳过了不可能匹配的字符串,所以在字符数量较大的情况下构造过程比较复杂,KMP的next数组构造就快多了,所以KMP算法要比暴力匹配算法好