2022年考研数据结构_4 串

https://gitee.com/fakerlove/Data-Structure

4. 串

4.1 模式匹配

1. 暴力算法 bf

从左到右一个个匹配,如果这个过程中有某个字符不匹配,就跳回去,将模式串向右移动一位。这有什么难的?

匹配不成功,i回溯到开始,j 回溯到子串的开头

匹配不成功,i 往后走

时间复杂度O(m*n)

2. KMP 算法

利用已经部分匹配这个有效信息,保持i指针不回溯,通过修改j指针,让模式串尽量地移动到有效的位置

时间复杂度O(m+n)

前缀,后缀,部分匹配值
  • 前缀:除去最后一个字符外,字符串的所有头部子串
  • 后缀:除去第一个字符外,字符串的所有头部子串
  • 部分匹配值:字符串的前缀和后缀最长相等的前后缀长度
字符串部分匹配值前缀后缀
a0 (空集 空集)空集空集
ab0 {a} {b}ab
aba1 {a,ab} {ba,a}ab aba a
abab2 {a,ab,aba} {b,ab,bab}a ab abab ab bab
ababa3 {a,ab,aba,abab} {a,ba,aba,baba}a ab aba ababa ba aba baba
ababc0 {a,ab,aba,abab} {c,bc,abc,babc}a,ab,aba,ababc,bc,abc,babc
sssss4s,ss,sss,sssss,ss,sss,ssss
abca1 {a,ab,abc} {a,ca,bca}a,ab,abca,ca,bca
next 数组 (子串回溯的位置)

  • 匹配的过程 KMP 算法的过程

    移动主串情况

    1. 如果是 j== -1 ,表示就是第一个字符匹配失败,第一个元素匹配失败,不需要移动子串,只需要移动主串

    2. 或者 字符串匹配成功

不移动主串的情况

  1. 匹配失败,子串回溯
  2. 右移的数字 = 已经匹配的字符数-对应的部分匹配值 j=next[j]+1
代码
int kmp(char str[],char temp[])//这个是查找
{
 
	int i = 0;//这个是主字符串的位置
	int j = 0;//这个是子字符串的位置
	int length1 = strlen(str);
	int length2 = strlen(temp);
	while (i<length1&&j<length2) 
	{
		if (j==-1||str[i] == temp[j]) {
			i++;
			j++;
		}
		else {
			j = next[j];
		}
	}
	if (j==length2) {
		return  i - j;
	}
	return  -1;
	
}
  • 代码 next 数组怎么求
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int next[1001];//这个是next数组
//函数声明
void getNext(char str[]);
int KMP(char str[],char temp[]);
int main()
{
	int i = 0;
	char str[1001];//这个是主字符串
	char temp[1001];//这个是用来匹配的字符串
	int length = 0;//这个是主字符串的长度。
	int result = -1;
 
	printf("请输入第一个字符串\n");
	gets(str);//在vs中用scanf_s();
	printf("请输入第二个字符串\n");
	gets(temp);//在vs中用scanf_s();
 
	getNext(str);//建立next数组
 
	result = KMP(str,temp);//这个是获取结果
 
        printf("\n");
 
	if (result <= 0) {
		printf("没有找到匹配的字符串");
	}
	else {
		printf("结果在主字符串的位置为 %d",result+1);
	}
	// system("pause");
	return  0;
}
void getNext(char str[])//next数组的建立,这个是关键
{
    // 初始化
	int i=0,j = -1;
	int length1 = strlen(str);
    // 第一个不匹配的话,是主串开始往后加一
	next[0] = -1;
	
	while (i < length1) {

        // -1 表示是第一个字符串,第一个字符串不需要赋值,因为肯定是-1 ,
        // 还有一种情况就是
		if ( j== -1 || str[j] == str[i]) {
			i++;
			j++;
            
			next[i] = j;
 
		}
		else {
			j = next[j];
		}
	}
}
int kmp(char str[],char temp[])//这个是查找
{
 
	int i = 0;//这个是主字符串的位置
	int j = 0;//这个是子字符串的位置
	int length1 = strlen(str);
	int length2 = strlen(temp);
	while (i<length1&&j<length2) 
	{
		if (j==-1||str[i] == temp[j]) {
			i++;
			j++;
		}
		else {
			j = next[j];
		}
	}
	if (j==length2) {
		return  i - j;
	}
	return  -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值