strstr函数与KMP算法比较

代码:

//KMP算法

#include <stdio.h>
#include <string.h>
#include<stdlib.h>
#include <sys/time.h>
#include <time.h>

//Copyright 1990 Software Development Systems, Inc.
char *strstr_1(const char *s1,const char *s2)
{
  int len2;
  if(!(len2=strlen(s2)))//此种情况下s2不能指向空,否则strlen无法测出长度,这条语句错误
    return(char*)s1;
  for(;*s1;++s1)
  {
      if(*s1==*s2 && strncmp(s1,s2,len2)==0)
      return(char*)s1;
}
  return NULL;
}

//Copyright 1986 - 1999 IAR Systems. All rights reserved
char* strstr_2(const char* s1,const char* s2)
{
    int n;
    if(*s2)
    {
        while(*s1)
        {
            for(n=0;*(s1+n)==*(s2+n);n++)
            {
                if(!*(s2+n+1))
                    return(char*)s1;
            }
            s1++;
        }
        return NULL;
    }
    else
        return (char*)s1;
}

//GCC-4.8.0
char *strstr_3(const char*s1,const char*s2)
{
    const char*p=s1;
    const size_t len=strlen(s2);
    for(;(p=strchr(p,*s2))!=0;p++)
    {
        if(strncmp(p,s2,len)==0)
            return (char*)p;
    }
    return(0);
}


//子字符串P[]对应的int数组next[]

void getNext(const char *P, int next[])
{
        int N=strlen(P);
        next[0]=0;
        next[1]=0;
        int k=0;
        int i=0;
        for(i=2;i<N;i++)
        {
                k=next[i-1];
                while(1)
                {
                        if(P[i-1]==P[k])
                        {
                                next[i]=k+1;
                                break;
                        }
                        else
                                k=next[k];
                        if(k==0)
                        {
                                next[i]=k;
                                break;
                        }
                }

        }


}



//利用KMP算法,从字符串T的第pos个字符起(pos>=0),验证字符串P是否为T的子字符串,如果是返回P第一个字母对应T的字符的
//位置,否则返回-1
int KmpCmp(const char *T,const char *P,int pos)
{
        int len=strlen(P);
        int *next=(int *)malloc(len*sizeof(int));
        getNext(P,next);
        int r=0;
        /*for(r=0;r<len;r++)
        {
                fprintf(stdout,"%d ",next[r]);
        }
        */
        //fprintf(stdout,"\n");


        int i=pos,j=0;
        while(T[i]!='\0' && P[j]!='\0')
        {
                if(T[i]==P[j])
                {
                        i++;
                        j++;
                }
                else
                {       if(j==0)
                                i++;
                        j=next[j];
                        //fprintf(stdout,"j=%d\n",j);
                }

        }
        if(P[j]=='\0')
        {
                free(next);
                return i-len;
        }
        else
        {
                free(next);
                return -1;
        }

}

int GetTime() 
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv.tv_sec * 1000000 + tv.tv_usec;
}

int main(int argc, char* argv[])
{
        //char T[]="adhelloworld";
        //char P[]="dh";
        const int len1=1024000;
        const int len2=1000;
        char T[len1];
        char P[len2];
        int i=0;
        srand(1001);
        for(i=0;i<len1;i++)
            T[i]=rand()%10+'0';
        for(i=0;i<len2;i++)
            P[i]=rand()%10+'0';
             // P[i]=T[i+len1-len2-23];

//test
 /*       for(i=0;i<len2;i++)
        {
            T[i]=i+'0';
            P[i]=i+'0';

        }
*/
        P[len2]=0;
        T[len1]=0;      
        //printf("%s\n",T);
        //printf("%s\n",P); 
        
        //strstr
        int startTime;
        char *p;
        startTime=GetTime();
        p=strstr_1(T,P);
        fprintf(stdout,"strstr1: %d\n",GetTime()-startTime);
      
        startTime=GetTime();
        p=strstr_2(T,P);
        fprintf(stdout,"strstr3: %d\n",GetTime()-startTime);

        startTime=GetTime();
        p=strstr_3(T,P);
        fprintf(stdout,"strstr3: %d\n",GetTime()-startTime);


        startTime=GetTime();
        p=strstr(T,P);
        fprintf(stdout,"strstr: %d\n",GetTime()-startTime);

        startTime=GetTime();
        int k=KmpCmp(T,P,0);
        //fprintf(stdout,"result: %d\n",k);
        fprintf(stdout,"kmp: %d\n",GetTime()-startTime);


        return 0;
}

iZ232ngsvp8Z:~/tmp # gcc -g -o kmp2 kmp2.c -O3

iZ232ngsvp8Z:~/tmp # ./kmp2

strstr1: 3026

strstr3: 2601

strstr3: 2257

strstr: 0

kmp: 4082

iZ232ngsvp8Z:~/tmp # gcc -g -o kmp2 kmp2.c

iZ232ngsvp8Z:~/tmp # ./kmp2

strstr1: 5264

strstr3: 4759

strstr3: 2746

strstr: 546

kmp: 8273

strstr_1 ,strstr_2,strstr_3 实现来自:strstr百度百科

不过计算结果还是令人惊讶的,自带的strstr算法远远优于其它几种。

看了网上的一些讨论,有人说strstr在内部是汇编的,可能是吧,以后确认。

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/huguangshanse00/article/details/49404269
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞