您的位置:首页 > 其它

字符串匹配暴力匹配法和KMP匹配算法对比

2018-01-17 20:15 701 查看
暴力匹配算法和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算法要比暴力匹配算法好
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: