作用:就是在一个长字符串中找有没有这个子串的算法
基本思路:从子串的最后一个字符开始对比
先将t跟s进行比较,不匹配,s就叫做坏字符,直接移动4个位置
将t跟t进行比较,匹配,再将x跟a进行比较,不匹配
t就叫做“好后缀”,而a就叫做坏字符,将其移动
坏字符的当前位置-坏字符在子串中出现的位置个字符(我是以1开始算字符串的长度的,比较好记)但是你写代码时记得把我写的数字都减一个1,因为下标是以0开始
如果坏字符不在子串中就将其当成0来算
这里也就是移动3-0=3个位置
将t与x进行比较,不匹配,x是坏字符,将其移动4-3=1个位置
这时你会发现如果你用坏字符的公式得出的结果为-1,难道你还要退回去走不行,所以这时你就需要用到另一个公式
后移位数 = 好后缀的位置 (以”好后缀”的最后一个字符为准)– 模式串中的上一次出现位置(如果”好后缀”在模式串中没有重复出现,则它的上一次出现位置为0,否则为1)
在这两个公式里面比较出较大的那个,将其作为后移的位数
像这里,这时你需要走的位数为4-1=3位
继续从后一位开始比,匹配成功则程序结束。
#include<stdio.h>
#include<string.h>
int main()
{
char ss[]="thisisateexttext",s[]="text";
int i,j=strlen(s)-1,k,l,f,m,n,a;
for(i=j;i<strlen(ss);i+=l)
{
printf("%d ",i);
a=0;//用来记从后往前走了多少位才到坏字符的位置
l=0;//标记每次需往后移动多少位
m=f=i;n=j;//子串的最后一位和母串的最后一位的下标
//m用来标记好后缀的最后一个字符
while(ss[f]==s[n])
{
if(n==0)
break;
n--,f--;a++;
}
if(n==0&&ss[f]==s[n])
break;//一旦子串到了第一个的位置
//并且与母串第一个字符相等就退出循环
//否则就通过坏字符公式和好后缀公式来算移动位置
else
{
n=0;//用来判断在母串有没有重复的好后缀
for(k=0;k<=j;k++)
{
if(ss[f]==s[k])
{
l=(j-a)-k;//坏字符公式
}
if(f!=m)
{
if(ss[m]==s[k])
{
n++; //判断好后缀有没有重复出现
}
}
}
if(!l)//如果坏字符在子串中没有出现的情况
{
l=(j-a)+1;
}
if(n<2&&n>0)
{
m=strlen(s)+1; //如果重复出现,m就是子串的长度,否则+1
}
else
m=strlen(s);
if(m>l)
l=m;//比较两者
}
}
printf("\n%d ",i);
return 0;
}