7、串(strcpy strcat strcmp strlen)字符串查找 (BF KMP)

1、BF算法(暴力算法)(Brute Force):

字符串匹配问题:

主串:“ababcabcdabcdeb”

子串:“abcd”

子串个数:(1+n)*n/2+1

真子串个数:(1+n)*n/2

目的:在主串中找到子串第一次开始出现的位置。

**BF算法难点:**容易出错(i没有回退)
1、两两比较,如果相等,i++,j++,接着向后比
2、如果匹配到一半发现不相等了,就返回到主串中这趟比较的下一个位置,i=i-j+1,
j回退到0
3、如果主串中的i走出了位置,那么并不能判断是否找到了子串相匹配
4、只能利用j是否等于字串长度来判断是否找到

#include<stdio.h>
#include<assert.h>
#include<string.h>
/*
BF算法:唯一注意一点,容易出错(i没有回退)
1、两两比较,如果相等,i++,j++,接着向后比
2、如果匹配到一半发现不相等了,就返回到主串中这趟比较的下一个位置,i=i-j+1,
j回退到0
3、如果主串中的i走出了位置,那么并不能判断是否找到了子串相匹配
4、只能利用j是否等于字串长度来判断是否找到
*/
int BF_Search(const char* s1, const char* s2, int pos)//pos为从主串的pos下标开始找
{
	assert(s1 != NULL && s2 != NULL);
	if (pos < 0 || pos >= strlen(s1))
	{
		//return -1
		pos = 0;//默认改成从零号下标开始找
	}
	int len1 = strlen(s1);//保存主串长度
	int len2 = strlen(s2);//保存子串长度
	int i = pos;//主串开始位置
	int j = 0;//字串开始位置
	while (i < len1 && j < len2)
	{
		if (s1[i] == s2[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 1;//如不相等时回退到主串开始匹配的地方的下一个位置
			j = 0;
		}
	}
	if (j == len2)
	{
		return i - j;
	}
	else
	{
		return -1;
	}
}
int main()
{
	const char* s1 = { "adadadadacdda" };
	const char* s2 = { "dacd" };
	int a=BF_Search(s1, s2, 3);
	printf("%d\n", a);
}

在这里插入图片描述

优点:思想简单,好实现

**缺点:**效率低下,时间复杂度O(n*m)

2、KMP算法

kmp就是三个外国人名字,kmp主要思想就是不回退
在这里插入图片描述

找next数组

"abcdabcde": -1 0 0 0 0 1 2 3 4

"ababcababca":-1 0 0 1 2 0 1 2 3 4 5

**“ababcababcaba”:-1 0 0 1 2 0 1 2 3 4 5 6 **可以重复

获得子串next数组元素函数

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
//s2为子串
int* Get_next(const char* s2)//"ababcababcab"--->-1 0 0 1 2 0 1 2 3 4 5 6前两个必是-1和0
{
	assert(s2 != NULL);
	int len2 = strlen(s2);
	int* next = (int*)malloc(sizeof(int) * len2);
	assert(next != NULL);
	int j = 0;
	int k = -1;
	next[0] = -1; 
	next[1] = 0;
	while (j < strlen(s2))
	{
		if (s2[j] == s2[k] || k == -1)//比较如果
		{
			j++;
			k++;
			next[j] = k;
		}
		else
		{
			k = next[k];
		}
	}
	return next;
}

KMP算法:

int KMP(const char* s1, const char* s2, int pos)
{
	assert(s1 != NULL && s2 != NULL);
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	int i = pos, j = 0;
	int* next = Get_next(s2);
	if (pos<0 || pos>len2)
	{
		pos = 0;
	}
	while (i < len1&&j < len2)
	{
		if (j==-1 ||s1[i] == s2[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}
	}
	if (j >= len2)
	{
		return i - j;
	}
	else
	{

		return -1;
	}
}
int main()
{
	const char* s1 = { "adadadadacdda" };
	const char* s2 = { "cdda" };
	int a = KMP(s1, s2, 3);
	printf("%d\n", a);
}


	else
	{

		return -1;
	}
}
int main()
{
	const char* s1 = { "adadadadacdda" };
	const char* s2 = { "cdda" };
	int a = KMP(s1, s2, 3);
	printf("%d\n", a);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值