代码:
//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在内部是汇编的,可能是吧,以后确认。