子串的定位运算通常称为串的模式匹配
或串匹配。
串的模式匹配设有两个字符串S和T,设S为主串,也称
正文串
;设T为子串,也称模式
。在主串S中查找与模式T相匹配的子串,如果匹配成功,确定相匹配的子串中的第一个字符在主串S中出现的位置。
著名的模式匹配算法有BF算法和KMP算法,下面介绍BF算法。
模式匹配不一定是从主串的第一个位置开始,可以指定主串中查找的起始位置pos。
【算法步骤】
①分别利用计数指针 i 和 j 指示主串 S 和模式 T 中当前正待比较的字符位置,i 初值为pos
, j 初值为1
。
②如果两个串均未比较到串尾,即 i 和 j 分别小于等于 S 和 T 的长度时,则循环执行以下操作:
- S.ch[i] 和 T.ch[j] 比较,若相等,则 i 和 j 均分别指示串中下个位置,继续比较后续字符
- 若不等,指针后退重新开始匹配,从主串的下一个字符(i=i-j+2)起再重新和模式的第一个字符(j=1)比较
③如果j >T.length
,说明模式 T 中的每个字符依次和主串 S 的一个连续的字符序列相等,则匹配成功,返回和模式 T 中第一个字符相等的字符在主串 S 中的序号(i-T.length);否则称匹配不成功,返回0。
【算法描述】
int Index_BF(SString S,SString T,int pos)
{//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0
//其中,T非空,1 ≤pos≤ S.length
i=pos; j=1; //初始化
while( i<=S.length && j<=T.length) //两个串均未比较到串尾
{
if(S.ch[i]==T.ch[j])
{++i;++j;} //继续比较后续字符
else
{i=i-j+2;j=1;} //指针后退重新开始比较
}
if(j>T.length) return i-T.length; //匹配成功
else return 0; //匹配失败
}
【算法分析】
①最好情况下O(n+m)
,每趟不成功的匹配都发生在模式串的第一个字符与主串中相应字符的比较,例如:
S=“aaaaaba”
T=“ba”
②最坏情况下O(n×m)
,每趟不成功的匹配都发生在模式串的最后一个字符与主串中相应字符的比较,例如:
S=“aaaaaab”
T=“aab”
代码实现:
#include<stdio.h>
#include<string.h>
int lens,lent;
int Index_BF(char s[],char t[],int pos)
{
int i=pos; int j=1; //初始化
while( i<=lens && j<=lent) //两个串均未比较到串尾
{
if(s[i]==t[j])
{++i;++j;} //继续比较后续字符
else
{i=i-j+2;j=1;} //指针后退重新开始比较
}
if(j>lent) return i-lent; //匹配成功
else return 0; //匹配失败
}
int main()
{
char s[100],t[100];
int x,i;
gets(s);
gets(t);
lens=strlen(s);
lent=strlen(t);
for (i=lens;i>0;i--) //将主串所有元素全部后移
{
s[i]=s[i-1];
}
for (i=lent;i>0;i--) //将子串所有元素全部后移
{
t[i]=t[i-1];
}
x=Index_BF(s,t,1);
printf("%d",x);
//return 0;
}
这个是关于KMP算法的讲解KMP算法—串的模式匹配算法
借鉴:《数据结构》 严蔚敏