给定一个主串a和一个模式串b,求模式串是否在主串中出现,若出现了返回首字母的下标,否则返回-1
该bf算法属于一个暴力思想,如果a串的长度为m,b串的长度为n,那么该算法的最坏情况下的时间复杂度为O(m*n)
一般在匹配的时候很难达到O(m*n),故还被广泛应用
程序代码:
#include<stdio.h>
#include<string.h>
char a[110],b[110];
int bf();
int main()
{
scanf("%s%s",a,b);
printf("%d\n",bf());
return 0;
}
int bf()
{
int i,j,m,n;
m=strlen(a);
n=strlen(b);
i=0;
j=0;
while(i<m&&j<n)
{
if(a[i]==b[j])
{
i++;
j++;
}
else
{
i=i-j+1;
j=0;
}
}
if(j==n)
return i-j;
return -1;
}
上面的bf算法时间复杂度是O(m*n),接下来介绍一个时间复杂度为O(m+n)的,这个算法就是KMP,说真的,我刚开始学这个算法的时候没理解,只是把它背会了,过了一段时间没用过,然后就忘了,今天我又重新看了一遍,发现之前不理解的地方现在懂了,简单的介绍一下KMP吧,该算法就是进行字符串的匹配,例如主串是T串,子串是P串,那么在进行匹配的时候我们会发现,当有一个字符匹配失败时,不需要回到最初的位置,举个例子吧,如果一个字符串是ababac,当匹配到c时失败了,其实现在不需要回到主串中的一个a的位置。仔细观察子串你会发现,ababa中前三个字符和后三个字符一样,这就意味着,当匹配到c不同时,那么c之前的aba是相同的,所以对于子串来说直接从下标为3的b开始匹配即可,而对于主串来说就是匹配失败的下标的位置,继续往后比即可。
这就牵扯到对子串的处理,需要记录下,在当前位置其最长后缀也是其前缀的长度,即是next数组。
直接来代码吧
程序代码
#include<stdio.h>
#include<string.h>
char T[10010],P[10010];
int next[10010];
void GetNext(char *str);
int main()
{
int lenT,lenP,i,j;
scanf("%s%s",T,P);
GetNext(P);
lenT=strlen(T);
lenP=strlen(P);
i=0;
j=0;
while(i<lenT)
{
if(j==0&&T[i]!=P[j])
i++;
else if(j>0&&T[i]!=P[j])
j=next[j-1];
else
{
i++;
j++;
}
if(j==lenP)
break;
}
if(j==lenP)
printf("%d\n",i-lenP);
else
printf("-1\n");
return 0;
}
void GetNext(char *str)
{
int len=strlen(str);
int i,j;
i=1;
j=0;
next[0]=0;
while(i<len)
{
if(j==0&&str[i]!=str[j])
{
next[i]=0;
i++;
}
else if(j>0&&str[i]!=str[j])
j=next[j-1];
else
{
next[i]=j+1;
i++;
j++;
}
}
}