串(BF ,KMP算法),数组,和广义表

本文深入探讨了串模式匹配的基本概念,重点介绍了两种主要的模式匹配算法:BF算法和KMP算法。BF算法实现简单但效率较低,而KMP算法通过消除回溯显著提升了效率。此外,文章还提供了这两种算法的C++实现代码,帮助读者更好地理解和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)串是内容受限的线性表,他限定了表中的元素为字符.
串的两种基本存储结构:顺序存储(常用)和链式存储。
主要有BF算法和KMP算法。
BF算法实现简单,但存在回溯,效率低,时间复杂度为O(m*n)。
KMP算法对BF算法进行改进,消除了回溯,提高了效率,世间复杂度为O(m+n)
(2)多维数组可以看成是线性表的推广,其特点是结构中的元素本身可以是具有某种结构的数据,但属于统一数据类型。数组一般采用顺序存储结构。
(3)广义表是另外一种线性表的推广形式,表中的元素可以使称为原子的单个元素,也可以是一个子表,所以线性表可以看成广义表的特例。广义表的结构相当灵活,在某种前提下,他可以兼容线性表,数组,树和有向图等各种常用的数据结构。广义表的常用操作有取表头和取表尾。广义表常采用链式存储结构:头尾链表的存储结构和扩展线性链表的存储结构。

1)BF算法

①size()和length()这两个函数是用来计算string类对象或者即STL对象方法。都是计算字符串长度。
②strlen()是函数,参数必须是字符型指针(char
),计算从开始到结束(’\0‘),返回的长度大小不包括’\0’,也是计算字符长度。
③sizeof()是运算符,不能计算复杂内存分配空间大小。计算字符所占空间大小。
*

#include<stdio.h>
#include<string>
#include<iostream>

using namespace std;
int Index_BF(string& s,string& t)
{
	int i = 0, j = 0,count=0;
	while (i < s.size()&&j<t.size())
	{
		if (s.at(i) == t.at(j))
		{
			i++;
			j++;
			count++;
		}
		else
		{
			i=i-j+1;
			j = 0;
			count = 0;
		}
		if (count ==t.size())
		{
			cout << "模式匹配成功,起始位置是:" << i - count + 1 << endl;
			return (i - count + 1);
		}
	}
	cout << "字符串匹配失败!"<<endl;
	return 0;
}

int Index_BF(string s,string t,int pos)
{
	int i = pos, j = 0;
	while (i<=s.size()&&j<=t.size())
	{
		if (s[i] == t[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
		if (j > t.size())
		{
			cout << "模式匹配成功,起始位置是:" << i - t.size() << endl;
			return (i - t.size() + 1);
		}
	}
	cout << "字符串匹配失败!" << endl;
	return 0;
}

int main(void)
{
	string S;
	string T;
	
	cout << "请输入主串:";
	cin >> S;
	cout << endl;

	cout << "请输入模板T:";
	cin >> T;
	cout << endl;

	Index_BF(S,T,0);

	system("pause");
	return 0;
}

2)KMP算法

KMP算法详解

#pragma once
//str1为主串,str2为模式串,在str1中检查是否包含str2,存在则返回起始位置,不存在则返回-1
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> getnext(const string &str2, vector<int> next)
{
	next.clear();
	next.resize(str2.size());
	if (str2.length() == 1)
	{
		next[0] = -1;
		return next;
	}
	next[0] = -1;
	next[1] = 0;
	int len = str2.length();
	int i = 2, cn = 0;//cn为最长前缀的后一个字符
	while (i < len)
	{
		if (str2[i - 1] == str2[cn]) //如果前一个字符和cn对应的值相等
			next[i++] = ++cn;//如果相等则此处的值为,cn+1
		else if (cn > 0)
			cn = next[cn];//不等的话继续往前推
		else
			next[i++] = 0;//不等的话并未没法往前推就变为0
	}
	return next;
	
	/*for (int i = 0; i < str2.size(); i++)
	{
		cout << next[i];
	}*/
}
int kmp(const string &str1, const string &str2, vector<int> & next)
{
	int i1 = 0, i2 = 0;
	while (i1 < str1.length() && i2 < str2.length())
	{
		if (str1[i1] == str2[i2])//两者比对,相等则主串和模式串都加加
		{
			i1++;
			i2++;
		}
		else if (next[i2] == -1)//两者没有匹配则进一步判断i2是否还有回退的资格,如果等于-1说明已经退到头了,则只能i1++;
		{
			i1++;
		}
		else//还可以退,则i2回到到next数组指定的位置再进行比对
			i2 = next[i2];
	}
	return i2 == str2.length() ? i1 - i2 : -1;
	//如果str2已经扫描完了说明已经找到了,返回str1中找到的起始位置;如果没有扫描完说明没有找到返回-1;
}

#include"kmp.h"

int main()
{
	string str1, str2;
	cout << "请输入主串:";
	cin >> str1;
	cout << "请输入模式:";
	cin >> str2;

	vector<int> next1(255);
	vector<int> next2;
	next2=getnext(str2,next1);
	int k;
	k = kmp(str1, str2, next2);
	cout << "匹配成功,模式匹配的其实位置为:" << k;

	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值