转自编程之美
以下是解法:
参考代码如下:
BOOL FindStr(char str1[],char str2[])
{
int len=strlen(str1);
char *str3=(char*)malloc(len*2+1);
memset(str3,0,len*2+1);
int i=0;
while(i<2*len)
{
str3[i++]=str1[i%len];
}
cout<<str3<<endl;
char* p=strstr(str3,str2);
delete str3;
if(p==NULL)
return FALSE;
return TRUE;
}
int main()
{
char str[]="AABCD";
char str1[]="AABCDAC";
if(FindStr(str,str1))
cout<<"Find";
else
cout<<"Not Find"<<endl;
return 0;
}
然而下面来分析一下strstr的实现方式,如何才能高效
传统的strstr方案:
其复杂度较为高,以下是我在网络上看到有人写的一个strstr的函数:
//初级的strstr
char * StrStr_1(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;
}
有上述代码可以看出来,她没有充分利用模式串s2本身的特性。例如对于ababac这样的模式串来说,当匹配到第四个字abac的时候出现了不匹配的元素,模式串不需要重新从0开始,只需要回退到next[b]=1的位置处就行了。
以下是使用KMP算法来处理strstr函数
void getNext(char *p,int *next)
{
int j,k;
next[0]=-1;
j=0;
k=-1;
while(j<strlen(p)-1)
{
if(k==-1||p[j]==p[k])
{
j++;
k++;
next[j]=k;
}
else
k=next[k];
}
}
//s目标串 p模式串
int strstr_1(char *s,char* p)
{
int next[100];
int i,j;
i=0;j=0;
getNext(p,next);
while(i<strlen(s))
{
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else
j=next[j];
if(j==strlen(p))
return i-strlen(p);
}
return -1;
}
int main()
{
char str1[]="ababac";
char str2[]="abac";
int i=strstr_1(str1,str2);
cout<<i<<endl;
//char *p=StrStr_1(str1,str2);
//if(p)
// cout<<*p<<endl;
//else
// cout<<"Not"<<endl;
return 0;
}
解法三:我们可以使用旋转字符串来处理,例如AABCD和BCDA,那么就旋转AABCD的BCDAA再一次扫描strlen(BCDA)长度的BCDAA看是否匹配。时间复杂度可以降低到
AABCD中出现B的次数m*(strlen(BCDA)。
代码略