朴素字符串匹配与Karbin-Karp算法

本文介绍了两种字符串匹配方法:朴素字符串匹配方法与Rabin-Karp算法。朴素方法通过逐字符比较来寻找模式串在文本中的位置,时间复杂度为O(nm)。Rabin-Karp算法利用哈希函数减少不必要的比较,预处理时间为O(m),平均运行时间为O(n)。


     字符串的精度匹配就是在文本T中找出模式P的精确副本,并求出匹配的位置下标。即如果P[0...m-1]==T[k...k+m-1] ,则称P与T的子序列匹配成功。我们要找出所有匹配成功的k。

     朴素字符串匹配方法很简单。从文本T的第一个字母和模式P的第一个字母开始比较。如果不匹配,就从T的第二个字母开始匹配,依次类推,不保留所有有用得信息。设P和T的长度分别为m和n .这种算法有两层循环,没有预处理时间,算法时间复杂度为O(nm)。

void Naive_String_Match(string T, string P){
	int n,m,pos,i;
	n = T.size();
	m = P.size();
	pos = i = ans=0;
	while (pos <=n - m){
		i = 0;
		while (i < m&&P[i] == T[pos + i])
			i++;
		if (i == m)    //循环跳出时当 i==m就表示匹配成功
			postion[ans++] = pos;
		pos++;
	}
}

其中postion[]数组保存了匹配成功的 k 值。

另外一种改进的办法叫做Rabin-Karp算法。这个算法在实际应用中可以较好的运行。Rabin-karp算法预处理时间是O(m) .平均运行时间是O(n)(m<=n),在最坏情况下运行时间为O(mn) .首先在初等数论中有以下结论 :

    设 a,b,q为3个正整数,则有:

                         1)(a+b) mod q= (a%q+b%q)%q

                         2)a×b mod q =(a mod q)×(b mod q) mod q

设组成T和P的字符组成的集合是 A,例如A={'a','b'...'z'} .则A中字符的个数记为 |A| .算法的核心思想是将模式p通过一个hash函数映射为一个整数值 ,也将于p匹配的那部分T[pos...pos+m-1]映射为一个整数值,如果hash[p]!=hash[T]则他们一定不匹配,但是如果hash[T]==hash[p]则不一定匹配,这时候需要一个一个字母的比较。至于计算hash[p],我们可以通过霍纳法则来求,时间为O(m).

而对于hash[T]的值,我们需要开始计算出T[0...m-1]的值H(0),在计算H(t)时不需要重新计算,可以通过H(t-1)获得:

                         H(t)=((H(t-1)-T[pos])*|A|^m)*|A|+T[pos+m] )mod Prime;

这个式子使用的|A|进制,同时需要一个素数作为模运算。在一开始就可以把中间|A|^m计算出来,于是可以不用每次都计算|A|^m.具体代码如下,选择的是A={'a','b'...'z'},即26进制:

#include<iostream>
#include<string>
using namespace std;
#define p 82595483
void Match(string W, string T);
int postion[1001];
int ans;
int main(){
	int i;
	string W, T;
	cin >> W >> T;
	Match(W, T);
	for (i = 0; i < ans; i++)
		cout << postion[i] << endl;
	return 0;
}
void Match(string W, string T){
	int pos, n, m, i, t,h,d;
	n = T.size();
	m = W.size();
	h=t =pos=ans=0;
	d = 1;
	for (i = 0; i < m; i++){
		t = (t * 26 + W[i] - 'a') % p;      
		h = (h * 26 + T[i] - 'a') % p;
		d = (d * 26) % p;
	}
	while (pos <=n-m){
		if (h == t){
			i = 0; 
			while (i < m&&W[i] == T[i + pos])
				i++;
			if (i == m)
				postion[ans++]=pos;
		}
	    h = (26 * h - (T[pos] - 'a')*d + (T[pos + m]-'a')) % p;
		pos++;
	}
}


根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法来实现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
本系统采用微信小程序作为前端交互界面,结合Spring BootVue.js框架实现后端服务及管理后台的构建,形成一套完整的电子商务解决方案。该系统架构支持单一商户独立运营,亦兼容多商户入驻的平台模式,具备高度的灵活性扩展性。 在技术实现上,后端以Java语言为核心,依托Spring Boot框架提供稳定的业务逻辑处理数据接口服务;管理后台采用Vue.js进行开发,实现了直观高效的操作界面;前端微信小程序则为用户提供了便捷的移动端购物体验。整套系统各模块间紧密协作,功能链路完整闭环,已通过严格测试优化,符合商业应用的标准要求。 系统设计注重业务场景的全面覆盖,不仅包含商品展示、交易流程、订单处理等核心电商功能,还集成了会员管理、营销工具、数据统计等辅助模块,能够满足不同规模商户的日常运营需求。其多店铺支持机制允许平台方对入驻商户进行统一管理,同时保障各店铺在品牌展示、商品销售及客户服务方面的独立运作空间。 该解决方案强调代码结构的规范性可维护性,遵循企业级开发标准,确保了系统的长期稳定运行后续功能迭代的可行性。整体而言,这是一套技术选型成熟、架构清晰、功能完备且可直接投入商用的电商平台系统。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值