常用字符串匹配算法

news2024/9/28 9:26:02

一、BF匹配

BF算法中的BF是Brute Force的缩写,中文叫作暴力匹配算法,也叫朴素匹配算法。
BF算法的时间复杂度很高,是O(nm),但在实际的开发中,它却是一个比较常用的字符串匹配算法。
第一,实际的软件开发中,大部分情况下,模式串和主串的长度都不会太大。而且每次模式串与主串中的子串匹配的时候,当中途遇到不能匹配的字符的时候,就可以就停止了,不需要把m个字符都对比一下。所以,尽管理论上的最坏情况时间复杂度是O(n
m),但是,统计意义上,大部分情况下,算法执行效率要比这个高很多。
第二,朴素字符串匹配算法思想简单,代码实现也非常简单。简单意味着不容易出错,如果有bug也容易暴露和修复。在工程中,在满性性能要求的前提下,简单是首选。

public class BFMate {
	public static void main(String[] args) {
		BFMate("adjhkljabclkffkk","abc");
	}
	public static boolean BFMate(String mainStr,String modelStr) {
		int len = mainStr.length()-modelStr.length();
		for(int i=0;i<len;i++) {
			if(modelStr.equals(mainStr.substring(i, i+modelStr.length()))) {
				System.out.println("main=="+mainStr.substring(i, i+modelStr.length()));
				return true;
			}
		}
		
		return false;
	}

}

二、BM匹配

BM(Boyer-Moore)算法。它是一种非常高效的字符串匹配算法。

BM算法核心思想是,利用模式串本身的特点,在模式串中某个字符与主串不能匹配的时候,将模式串往后多滑动几位,以此来减少不必要的字符比较,提高匹配的效率。BM算法构建的规则有两类,字符规则和好后缀规则。好后缀规则可以独立于坏字符规则使用。因为坏字符规则的实现比较耗内存,为了节省内存,我们可以只用好后缀规则来实现BM算法。

public class BMMate {
	private final int Size = 256;
	public void generateBC(char[] b,int m,int[] bc) {
		for(int i=0;i<Size;i++) {
			bc[i] = -1;//初始化bc
		}
		
		for(int i=0;i<=m;i++) {
			int ascii = (int)b[i];//计算b[i]的ASCII值
			bc[ascii] = i;//b[i]在bc中的位置
		}
	}
	
	//b表示模式串,m表示长度,suffix、prefix数组事先申请好了
	private static void generateGS(char[] b,int m,int[] suffix,boolean[] prefix) {
		for(int i=0;i<m;i++) {//初始化
			suffix[i] = -1;
			prefix[i] = false;
		}
		
		for(int i=0;i<m-1;i++) {//b[0,i]
			int j=i;
			int k=0;//公共后缀子串长度
			while(j>=0&&(b[j] == b[m-1-k])) {//与b[0,m-1]求公共后缀子串
				--j;
				++k;
				suffix[k]=j+1;//j+1表示公共后缀子串在b[0,i]中的起始下标
				System.out.println("i="+i+",j="+j);
				System.out.println("suffix"+k+"="+suffix[k]);
			}
			
			if(j==-1) {
				prefix[k] = true;//如果公共后缀子串也是模式串的前缀子串
				System.out.println("prefix"+k+"="+prefix[k]);
			}
		}
	}
	
	public int bm(char[] a,int n,char[] b,int m) {
		int [] bc = new int[Size];//记录模式串中每个字符最后出现的位置
		generateBC(b,m,bc);//构建坏字符哈希表
		int[] suffix = new int[m];
		boolean[] prefix = new boolean[m];
		generateGS(b,m,suffix,prefix);
		int i=0;//表示主串与模式串第一个字符对齐
		while(i<n-m) {
			int j=0;
			for(j=m-1;j>=0;j--) {//模式串从后往前匹配
				if(a[i+j] != b[j]) break;
			}
			
			if(j<=0) return i;//匹配成功,返回主串与模式串第一个匹配字符的位置
			
			
			int x = j-bc[(int)a[i+j]];
			int y = 0;
			if(j<m-1) {//如果有好后缀的话
				y = moveByGS(j,m,suffix,prefix);	
			}
			
			i = i+Math.max(x, y);
		}
		return -1;
	}
	
	//j表示坏字符对应的模式串中的字符下标;m表示模式串长度
	private int moveByGS(int j,int m,int[] suffix,boolean[] prefix) {
		int k=m-1-j;//好后缀长度
		
		if(suffix[k] != -1) {
			return j-suffix[k]+1;
		}
		
		for(int r = j+2;r<=m-1;++r) {
			if(prefix[m-r]==true) {
				return r;
			}
		}
		return m;
	}
}

三、Trie树

Trie树,也叫“字典树”。顾名思义,它是一个树形结构。它是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题。
在这里插入图片描述

/**
 * 假设插入的数据只包含26个小写字母组成的单词
 * 将26个字母映射的一个长度26的数组中,下标0-25分别对应a-z
 * 
 * 插入字符串时间复杂度 : O(n),n表示所有字符串的长度和
 * 查找字符串时间复杂度 : O(k),k表示要查找的字符串的长度
 * 
 * Trie树不适合精确匹配查找,这种问题更适合用散列表或者红黑树来解决。
 * Trie树比较适合的是查找前缀匹配的字符串,类似实现搜索关键词的提示功能。
 */
public class TrieTree {
	private TrieNode root = new TrieNode('/');//存储无意义字符串
	
	public class TrieNode {
		public char data;
		public TrieNode[] children = new TrieNode[26];
		public boolean isEndingChar;
		
		public TrieNode(char data) {
			this.data = data;
		}
	}
	
	//往Trie树中插入一个数据
	public void insert(char[] data) {
		TrieNode node = root;
		for(int i=0;i<data.length;i++) {
			if(node.children[data[i]-'a']==null) {
				node.children[data[i]-'a'] = new TrieNode(data[i]);
			}
			node = node.children[data[i]-'a'];
		}
		node.isEndingChar = true;
	}
	
	//在Trie树中查找一个数据
	public boolean find(char[] data) {
		TrieNode node = root;
		for(int i=0;i<data.length;i++) {
			if(node.children[data[i]-'a']==null) {
				return false;//不存在
			}
			node = node.children[data[i]-'a'];
		}
		if(node.isEndingChar==false) {
			return false;//不是完全匹配
		}else {
			return true;//完全匹配
		}
	}
}
public class TestTrieTree {
	public static void main(String[] args) {
		TrieTree tree = new TrieTree();
		//how,hi,her,hello,so,see
		tree.insert(new char[] {'h','o','w'});
		tree.insert(new char[] {'h','i'});
		tree.insert(new char[] {'h','e','r'});
		tree.insert(new char[] {'h','e','l','l','o'});
		tree.insert(new char[] {'s','o'});
		tree.insert(new char[] {'s','e','e'});
		System.out.println(tree.find(new char[] {'h','i'}));
		
		System.out.println(tree.find(new char[] {'h','a'}));
		
	}
}

运行结果

true
false

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/906858.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全(黑客)自学笔记建议

前言 1.不要试图以编程为基础的学习开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而且实际向安全过渡后可用到的关键知识并不多 一般人如果想要把编程学好再开…

安防视频监控平台EasyCVR视频集中存储平台接入RTSP设备出现离线情况的问题解决方案

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

Web Worker的使用

Web Worker 前言一、Web Worker是什么&#xff1f;二、使用步骤2.1 创建 Web Worker2.2 监听消息2.3 发送消息 三、优点与缺点3.1 优点3.2 缺点 总结 前言 JavaScript采用的是单线程模型&#xff0c;也就是说&#xff0c;所有任务只能在一个线程上完成&#xff0c;一次只能做一…

【leetcode 力扣刷题】 两数/三数/四数之和 哈希表和双指针解题

两数/三数/四数之和 题目合集 哈希表求解1. 两数之和454. 四数相加Ⅱ 双指针求解15.三数之和18. 四数之和 这个博客是关于&#xff1a;找出数组中几个元素&#xff0c;使其之和等于题意给出的target 这一类题目的&#xff0c;但是各个题之间又有些差异&#xff0c;使得需要用不…

lwIP更新记10:IP 冲突检测

lwip-2.2.0-rc1 版本于 2023 年 6 月 29 日发布&#xff0c;带来了我期盼已久的 IPv4 冲突检测 功能。 lwip-2.2.0-rc1 版本重新回归了 master 分支&#xff08;主分支&#xff09;&#xff0c;不再使用单独的稳定分支。 master 分支 是一个 Git&#xff08;版本控制程序&…

C#8.0本质论第四章--操作符和控制流程

C#8.0本质论第四章–操作符和控制流程 4.1操作符 有些操作符以符号的形式出现&#xff0c;例如、-、?.或者??等&#xff0c;而另一些操作符则为关键词&#xff0c;例如default和is。 4.1.1一元正负操作符 一元正操作符()对值几乎没有影响&#xff0c;它在C#中是多余的。…

python 连接Redis 数据库

pip install redis python代码 import redis# 连接数据库 r redis.Redis(host192.168.56.15, port6379, db0)# 存储数据 #r.set(key, value) r.set(name, zaraNet)# 获取数据 value r.get(name) print(value)# 关闭连接&#xff08;可选&#xff09; r.close()

AP9196 DC-DC 升压 升降压 恒流电源管理芯 LED电源驱动IC

产品说明 AP9196 是一系列外围电路简洁的宽调光比升压调光恒流驱动器&#xff0c;适用于 3-40V 输入电压范围的 LED照明领域。AP9196 采用我司专利算法&#xff0c;可以实现高精度的恒流效果&#xff0c;输出电流恒流精度≤3&#xff05;&#xff0c;电压工作范围为5-40V&…

Redis 缓存满了怎么办?

引言 Redis 缓存使用内存来保存数据&#xff0c;随着需要缓存的数据量越来越大&#xff0c;有限的缓存空间不可避免地会被写满。此时&#xff0c;应该怎么办&#xff1f;本篇文章接下来就来聊聊缓存满了之后的数据淘汰机制。 值得注意的是&#xff0c;在 Redis 中 过期策略 和…

【rar密码】rar压缩包密码列表

之前给大家介绍过WinRAR自动加密的设置方法&#xff0c;今天再介绍一种RAR压缩包加密方法&#xff1a;整理密码。 什么是整理密码&#xff1a; 在加密rar文件的时候&#xff0c;点击下拉框选择密码&#xff0c;不用输入密码 设置方法&#xff1a; 前面的操作步骤和设置自动…

正中优配:尾盘拉升的股票第二天的走势?

尾盘拉升是指买卖日快结束时股票价格呈现上涨的状况。关于许多投资者来说&#xff0c;这一般是好事情&#xff0c;因为它可认为他们带来更高的收益。但是&#xff0c;人们常常会问尾盘拉升的股票第二天的走势怎么。本文将从多个角度进行剖析。 首要&#xff0c;咱们需求认识到这…

这所211太好考了!263分上岸!平均分300分!

一、学校及专业介绍 宁夏大学&#xff08;Ningxia University&#xff0c;简称&#xff1a;宁大&#xff09;&#xff0c;是中国教育部与宁夏回族自治区人民政府合建高校&#xff0c;位列国家“双一流”“211工程”重点建设高校&#xff0c;国家“中西部高校综合实力提升工程”…

cpolar+JuiceSSH实现手机端远程连接Linux服务器

文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …

成绩管理神器

各位老师们是不是需要一款方便快捷班级查询工具&#xff1f;其实易查分就可以帮助老师和学生轻松地管理和查询成绩。查分系统是现代教育管理的一项重要工具&#xff0c;传统纸质成绩单已被易查分电子成绩单所取代&#xff0c;带来了方便快捷等多种优势&#xff0c;为学生、家长…

scroll 和 wheel 事件的区别

listRef.addEventListener(“scroll”, onScroll)&#xff0c;onScroll 里面打 log 打不出来。 我觉得 list 是一个长的列表&#xff0c;比 container 要长&#xff0c;应该能滚动才是&#xff0c;不知道为啥滚动不了 当时我想到的是可能电视不支持这个事件&#xff0c;但是问…

OSCS开源安全周报第 56 期:Apache Airflow Spark Provider 任意文件读取漏洞

本周安全态势综述 OSCS 社区共收录安全漏洞 3 个&#xff0c;公开漏洞值得关注的是 Apache NiFi 连接 URL 验证绕过漏洞(CVE-2023-40037)、PowerJob 未授权访问漏洞(CVE-2023-36106)、Apache Airflow Spark Provider 任意文件读取漏洞(CVE-2023-40272)。 针对 NPM 、PyPI 仓库…

饼图的legend文字太长和数量太多处理

legend文字太长和数量太多 在我们使用图表饼图的时候会发现因为数据太多导致页面的布局发现重叠或者不好看&#xff0c;比如label的文字太长了&#xff0c;legend的数量太多了等一些问题&#xff0c;所以今天我们就来聊聊遇到这些问题的是可以通过那些设置来进行改进 文字太长…

第12步---MySQL的JDBC操作

第12步---MySQL的JDBC操作 1.概述 采用Java API 的方式实现数据之间的操作。 根据不同的数据库采用了不同的驱动&#xff0c;接口是一致的。 下载的地址 MySQL :: Download MySQL Connector/J (Archived Versions) 2.执行流程 注册驱动 创建连接 执行sql语句的对象 结果…

10个最受欢迎的免费STL模型下载网站【2023】

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 你是否决定立即购买 3D 打印机&#xff1f; 或者可能一直在考虑并正在寻找更多细节来了解它如何使您受益&#xff1f; 好吧&#xff0c;总有一天&#xff0c;你拥有 3D 打印活动所需的所有知识和资源&#xff0c;但没有时…

【SpringCloud】SpringCloudAlibaba官网资料

出现原因 Spring Cloud Netflix Projects Entering Maintenance Mode 官网 博客 https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md官网 https://spring.io/projects/spring-cloud-alibaba#overview英文 https://github.com/alibaba/spring-cloud-…