串的定位操作(BF算法)

算法功能

若串T是串S的子串,则返回串T在串S中第一次出现的位置;否则返回-1

算法思想

首先将i, j分别指向串S和串T,如果对应位置字符相同,则比较下一个字符;如果不相同则令i=i-j+1,且j=0,又进行下一次的串T的首字节比较。一直循环下去,直到i或j指向串尾。循环结束后,若j等于串T的长度,则说明串T是串S的子串,返回其首次出现的起始位置;否则直接返回-1

核心代码

int Idx (String* S, String* T)
{
	int i = 0, j = 0;
	int k;
	
	while (i < S->Len && j < T->Len)
	{
		if (S->ch[i] == T->ch[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i-j+1;
			j = 0;
		}
	}
	
	if (j == T->Len)
	{
		k = i-T->Len+1;
		return k;
	}
	else
	{
		k = -1;
		return k; 
	}
}

虽然算法很简单,但是第一次接触可能会有点懵,下面我们来举个例子,加深理解

过程举例

假设串S中的字符为“aabceabcdf” ,串T中的字符为"abcd"。

刚开始i=0, j=0
在这里插入图片描述

因为S->ch[0]和T->ch[0]相等,所以i=i+1=1,j=j+1=1
在这里插入图片描述
因为S->ch[1]和T->ch[1]不相等,所以i=i-j+1=1,j=0
在这里插入图片描述
因为S->ch[1]和T->ch[0]相等,所以i=2,j=1
在这里插入图片描述
相等,所以i=3, j=2
在这里插入图片描述

相等,所以i=4, j=3

在这里插入图片描述
不相等,所以i= i+j-1=2, j=0
在这里插入图片描述
以此类推下去…
在这里插入图片描述
直到i=9, j=4,因为此时j的值与串T的长度相等,所以退出循环,k就等于6,返回k的值

上面的例子是关于串T是串S的子串的情况,还有另一种情况,即串T不是串S的子串,读者可以举个例子,尝试自己动手写出推理过程,可以更好地掌握这个算法噢

源代码

# include <stdio.h>
# define MAX 100

typedef struct 
{
	int Len;
//字符串的长度	
	char ch[MAX];
//字符数组	
}String;


int Idx (String* S, String* T)
{
	int i = 0, j = 0;
	int k;
	
	while (i < S->Len && j < T->Len)
	{
		if (S->ch[i] == T->ch[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i-j+1;
			j = 0;
		}
	}
	
	if (j == T->Len)
	{
		k = i-T->Len+1;
		return k;
	}
	else
	{
		k = -1;
		return k; 
	}
}


int main ()
{
	int k; 
	String S, T;
	printf ("请输入串S中的字符:");
	gets (S.ch);
	printf ("请输入串S的长度:");
	scanf ("%d", &S.Len);
	getchar ();
//吸收回车键	
	printf ("请输入串T中的字符:");
	gets (T.ch);
	printf ("请输入串T的长度:");
	scanf ("%d", &T.Len);
	
	k = Idx (&S, &T);
	if (k == -1)
	{
		printf ("\n串T不是串S的子串!!!");
	}
	else
	{
		printf ("\n串T为串S的子串,第一次出现的位置为:%d", k);
	} 
}

运行结果

在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值