字符串匹配算法(BF RK)

文章目录

    • 1. BF(Brute Force)暴力匹配
      • BF代码
    • 2. RK(Rabin-Karp)算法
      • RK代码
    • 3. 思考题:(二维匹配)

1. BF(Brute Force)暴力匹配

BF算法的思想,在主串中,检查起始位置分别是0、1、2…n-m且长度为m的n-m+1个子串,看有没有跟模式串匹配的。最坏情况下每次都要对比m个字符,对比次数n-m+1次,复杂度O(m*n),适用小规模字符串匹配
在这里插入图片描述

BF代码

/*** @description: BF暴力匹配* @author: michael ming* @date: 2019/6/17 20:11* @modified by: */
#include <string>
#include <iostream>
using namespace std;
int str_BFM(string s, int pos, string t)
{if(s.length()== 0 || t.length() == 0)return 0;int i = pos - 1, j = 0;while(i < s.length() && j < t.length()){if(s[i] == t[j]){i++;j++;}else//字符串匹配失败,主串查找开始位置i+1,模式串从头开始{i = i - j + 1;j = 0;}}if(j >= t.length())return i-j+1;elsereturn 0;
}
int main()
{string a = "ababcabcacbab", b = "abcac";cout << a << "中第一次出现" << b << "的位置是:" << str_BFM(a,1,b) << endl;return 0;
}

在这里插入图片描述

2. RK(Rabin-Karp)算法

  • 上面BF算法,每次检查主串与子串是否匹配,需要逐次对比每个字符
  • 引入哈希,降低复杂度
  • RK算法思路:对n-m+1个子串分别求哈希值,然后与模式串的哈希值比较;如果某个子串的哈希值和模式串的哈希值匹配(需要考虑哈希冲突),比较数字是否相等是非常快的,所以效率比BF效率高
    在这里插入图片描述
  • But, 计算子串的哈希值的时候,需要遍历每个字符;虽然比较效率高了,但是整体效率没有提高
  • 哈希算法设计技巧:K进制数表示子串(无冲突)(K为字符集内字符种数)
  • K进制法,相邻子串的哈希值计算公式有一定的关系:
    在这里插入图片描述
    在这里插入图片描述
  • 26(m-1)可以提前算好存放在数组中,指数就是数组的下标,计算26的x次方时,直接去数组下标x位置读取
    在这里插入图片描述
  • 复杂度,计算子串哈希值需要扫描一遍主串O(n);比较n-m+1个子串哈希值O(n);所以整体复杂度O(n)(取决于哈希函数冲突概率)
  • 问题:如果模式串很长,子串的哈希值很大,超过计算机可表示的范围,怎么办?
    针对哈希值范围溢出,改造哈希函数:
    (1) 将a对应1,以此类推z对应26,将字符串每个字符对应数字相加作为哈希值,值的范围小了 (但是冲突概率有点大)
    (2) 将每个字符对应一个质数(冲突概率降低)
  • 存在冲突的情况下,如果模式串和子串哈希值相等,再比较一下它两真的相等否。
  • 哈希算法冲突概率要比较低,否则RK算法复杂度退化,效率下降

RK代码

/*** @description:RK匹配算法,计算子串哈希值,进行对比* @author: michael ming* @date: 2019/6/17 22:40* @modified by: */
#include <string>
#include <iostream>
using namespace std;
bool same(char* a, char* b, int m)
{for(int i = 0; i < m; ++i){if(a[i] != b[i])return false;}return true;
}
int str_RK(string s, string t)//s是主串,t是模式串
{int n = s.length(), m = t.length();int table[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};//质数表对应a-zint i, j, hash_val, value = 0;for(i = 0; i < m; ++i) //计算模式串的hash值value{value += table[t[i]-'a'];}for(i = 0; i < n-m+1; ++i)//最多n-m+1次比较{hash_val = 0;for(j = i; j < m+i; ++j)//计算第i个子串的哈希值{hash_val += table[s[j]-'a'];}if(hash_val == value && same(&s[i],&t[0],m)){//如果子串哈希值等于模式串的,且"真的"字符串匹配(避免冲突带来的假匹配)return i+1;//返回匹配位置,第i位开始,i从1开始}}return 0;
}
int main()
{string a = "ababcabcacbab", b = "abcac";cout << a << "中第一次出现" << b << "的位置是:" << str_RK(a,b) << endl;return 0;
}

在这里插入图片描述
如果不检查冲突,删除以下条件,匹配会出错

same(&s[i],&t[0],m)

在这里插入图片描述

3. 思考题:(二维匹配)

在这里插入图片描述
对RK算法进行改造得到答案
nr 主串行数
nc 主串列数
mr 模式串行数
mc 模式串列数
复杂度则为O((nr-mr+1)*(nc-mc+1)),简写为O(nr * nc)

/*** @description: 2维字符串匹配* @author: michael ming* @date: 2019/6/18 0:07* @modified by: */
#include <iostream>
#define nr 5    //主串行数
#define nc 5    //主串列数
#define mr 2    //模式串行数
#define mc 2    //模式串列数
int cal_hash_t(int* table, int r, int c, char ch[][mc])
{int i, j, value = 0;for (i = 0; i < r; ++i) //计算2d模式串的hash值value{for(j = 0; j < c; ++j)value += table[ch[i][j]-'a'];}return value;
}
int cal_hash_s_child(int* table, int i0, int j0, int r, int c, char ch[][nc])
{int i, j, hash_value = 0;for (i = i0; i < r; ++i) //计算2d子串的hash值value{for(j = j0; j < c; ++j)hash_value += table[ch[i][j]-'a'];}return hash_value;
}
bool same(char s[][nc], char t[][mc], int i0, int j0)
{int x = i0, y = j0, i, j;for(i = 0; i < mr; ++i,++x){for(j = 0, y = j0; j < mc; ++j,++y)//记得写y=j0,换行后y复位{if(s[x][y] != t[i][j])return false;}}return true;
}
bool str_RK_2d(char s[][nc], char t[][mc])//s是主串,t是模式串
{int table[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};//质数表对应a-zint i, j, hash_val, value;value = cal_hash_t(table,mr,mc,t);//计算2d模式串哈希值for(i = 0; i < nr-mr+1; ++i)//行最多nr-mr+1次比较{for(j = 0; j < nc-mc+1; ++j)//列最多nc-mc+1次比较{hash_val = cal_hash_s_child(table,i,j,mr+i,mc+j,s);//计算2d子串哈希值if(hash_val == value && same(s,t,i,j)){//如果2d子串哈希值等于模式串的,且"真的"字符串匹配(避免冲突带来的假匹配)std::cout << "找到模式矩阵,其左上角在 " << i+1 << " 行," << j+1 << " 列." << std::endl;return true;}}}return false;
}int main()
{char s[  ][nc] = {{ 'a', 'b', 'a', 'b', 'a' },{ 'a', 'b', 'a', 'b', 'a' },{ 'a', 'b', 'b', 'a', 'a' },{ 'a', 'b', 'a', 'a', 'b' },{ 'b', 'b', 'a', 'b', 'a' }};char t[  ][mc] = {{ 'a', 'b' },{ 'b', 'a' }};str_RK_2d(s,t);char a[  ][nc] = {{ 'd', 'a', 'b', 'c' },{ 'e', 'f', 'a', 'd' },{ 'c', 'c', 'a', 'f' },{ 'd', 'e', 'f', 'c' },{ 'b', 'b', 'a', 'b' }};char b[  ][mc] = {{ 'c', 'a' },{ 'e', 'f' }};str_RK_2d(a,b);return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

用Python寻找最优投资组合

原文地址&#xff1a;https://www.jianshu.com/p/2a25dfd465e9 现代投资组合理论&#xff08;Modern Portfolio Theory&#xff0c;MPT&#xff09;告诉我们投资者应该分散投资来实现最小化风险最大化投资回报。大邓刚开始学习这方面知识&#xff0c;用了将近一天的时候才搞懂M…

技术动态 | 事理图谱,下一代知识图谱

本文转载自公众号&#xff1a;DataHorizon。 人工智能与认知智能当前人工智能时代下&#xff0c;机器与人类之间的博弈一直在进行着。如图1所示&#xff0c;从1926年达特茅斯会议的召开标志人工智能诞生到深度学习模型在…

头条Java后台3面(含答案):事务+List集合+慢查询SQL+Redis+秒杀设计

头条Java一面 1.讲讲jvm运行时数据库区 2.讲讲你知道的垃圾回收算法 3.jvm内存模型jmm 4.内存泄漏与内存溢出的区别 5. select、epoll 的区别&#xff1f;底层的数据结构是什么&#xff1f; 6.mysql数据库默认存储引擎&#xff0c;有什么优点 7.优化数据库的方法&#xf…

CNN卷积神经网络(吴恩达《卷积神经网络》笔记一)

CNN 卷积网络说明卷积 Convolution填充 Padding步长 StrideRGB图像卷积池化 Pooling完整CNN为什么人们喜欢用卷积神经网络&#xff1f;实例分析说明 关于CNN的基础知识&#xff1a;卷积、填充、步长、池化、完整的深度CNN网络可以参考 链接: AI学习笔记——卷积神经网络&#…

字符串匹配算法(BM)

文章目录1. BM&#xff08;Boyer-Moore&#xff09;算法1.1 坏字符规则1.2 好后缀规则1.3 两种规则如何选择2. BM算法代码实现2.1 坏字符2.2 好后缀2.3 完整代码2.4 调试3. 总结1. BM&#xff08;Boyer-Moore&#xff09;算法 思想&#xff1a;有模式串中不存在的字符&#xf…

SQL 数据分析常用语句

1 基础查询 • 2 字符串数字日期时间 • 3 聚合数据查询 • 4 子查询 • 5 联接组合查询 • 6 高级查询 • 7 更新数据 阅读提醒&#xff1a;点击图片放大可看清晰的 1 基础查询 2 字符串数字日期时间 3 聚合数据查询 4 子查询 5 联接组合查询 6 高级查询 7 更新数据 参考资料 …

开源词法分析工具LAC重大升级!打造属于自己的个性化分词器!

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术文 | 匿名大佬编 | 北大小才女小轶本文将为大家介绍如何使用百度开源的词法分析工具LAC实现个性化分词&#xff08;附代码&#xff09;&#xff0c;并展示LAC在各数据集上惊艳的性能表现。背景介绍分词是中文…

老刘说NLP:这几年的NLP历程回顾,以及关于NLP(知识图谱等)落地的思考

得语言者&#xff0c;得天下。得语言资源者&#xff0c;分天下。得语言逻辑者&#xff0c;争天下。 前言 只有把自己所思考的&#xff0c;所认识的东西&#xff0c;以文字的方式记录下来&#xff0c;才是对自己成长最好的记录方式。 是的&#xff0c;距离上一次动手写博客或者…

Redis系列教程(一):Redis缓存的设计、性能、应用与数据集群同步

Redis 是完全开源免费的&#xff0c;遵守BSD协议&#xff0c;是一个高性能的key-value数据库。Redis本质上是一个Key-Value类型的内存数据库&#xff0c;很像memcached&#xff0c;整个数据库统统加载在内存当中进行操作&#xff0c;定期通过异步操作把数据库数据flush到硬盘上…

论文浅尝 | 提取计数量词丰富知识库

OpenKG 祝各位读者新年快乐&#xff01;论文标题&#xff1a;Enriching Knowledge Bases with Counting Quantifiers论文链接&#xff1a;https://link.springer.com/content/pdf/10.1007%2F978-3-030-00671-6_11.pdf发表会议&#xff1a;ISWC 2018论文源码&#xff1a;https:/…

RNN循环神经网络(吴恩达《序列模型》笔记一)

1、为什么选择序列模型 2、数学符号 用1来代表人名&#xff0c;0来代表非人名&#xff0c;句子x便可以用y[1 1 0 1 1 0 0 0 0]来表示 3、循环网络模型 值得一提的是&#xff0c;共享特征还有助于减少神经网络中的参数数量&#xff0c;一定程度上减小了模型的计算复杂度。 …

字符串匹配算法(KMP)

文章目录1. KMP由来2. KMP算法基本原理3. 代码4. Leetcode 28. 实现 strStr()1. KMP由来 上一节说的BM算法是最高效、最常用的字符串匹配算法。最知名的却是KMP&#xff0c;它3位作者&#xff08;D.E.Knuth&#xff0c;J.H.Morris&#xff0c;V.R.Pratt&#xff09;&#xff0…

常用的SQL语句

常用的SQL语句 一、基础 1、说明&#xff1a;创建数据库 CREATE DATABASE database-name 2、说明&#xff1a;删除数据库 drop database dbname 3、说明&#xff1a;备份sql server 1 --- 创建 备份数据的 device 2 3   USE master 4 5   EXEC sp_addumpdevice disk, te…

论文浅尝 | 用对抗学习做知识表示(NAACL2018)

论文链接&#xff1a;https://arxiv.org/pdf/1711.04071.pdf代码链接&#xff1a;https:// github.com/cai-lw/KBGAN 本文针对在生成负样本时有大部分负样本可以很好地和正样本区分开&#xff0c;对训练的影响不大&#xff0c;提出了使用生成对抗网络&#xff08;GANs&#xff…

为什么搜索与推荐场景用AUC评价模型好坏?

星标/置顶小屋&#xff0c;带你解锁最萌最前沿的NLP、搜索与推荐技术文 | 吴海波在互联网的排序业务中&#xff0c;比如搜索、推荐、广告等&#xff0c;AUC&#xff08;Area under the Curve of ROC&#xff09;是一个非常常见的评估指标。网上关于AUC的资料很多&#xff0c;知…

Redis系列教程(九):Redis的内存回收原理,及内存过期淘汰策略详解

Redis内存回收机制 Redis的内存回收主要围绕以下两个方面&#xff1a; 1.Redis过期策略:删除过期时间的key值 2.Redis淘汰策略:内存使用到达maxmemory上限时触发内存淘汰数据 Redis的过期策略和内存淘汰策略不是一件事&#xff0c;实际研发中不要弄混淆了&#xff0c;下面会…

字符串匹配算法(Trie树)

文章目录1. Trie树概念2. Trie树操作2.1 存储2.2 查找2.3 插入2.4 删除2.5 打印3. 完整代码4. Trie树与散列表、红黑树的比较4.1 思考题参考文章5. 练习题1. Trie树概念 Trie树&#xff0c;也叫字典树&#xff0c;它是一个树形结构。是一种专门处理字符串匹配的数据结构&#…

论文浅尝 | 基于知识图谱嵌入的 Bootstrapping 实体对齐方法

来源: IJCAI 2018链接: https://www.ijcai.org/proceedings/2018/0611.pdf本文关注基于知识图谱嵌入(后文全部简称为知识嵌入)的实体对齐工作&#xff0c;针对知识嵌入训练数据有限这一情况&#xff0c;作者提出一种 bootstrapping 策略&#xff0c;迭代标注出可能的实体对齐&a…

大规模领域词汇库项目DomainWordsDict:涵盖68个领域、共计916万的词汇库资源开放

项目概述 DomainWordsDict, Chinese words dict that contains more than 68 domains, which can be used as text classification、knowledge enhance task。涵盖68个领域、共计916万词的专业词典知识库&#xff0c;可用于文本分类、知识增强、领域词汇库扩充等自然语言处理应…

递归」与「动态规划

原文地址&#xff1a;https://juejin.im/post/5c2308abf265da615304ce41#heading-8 在学习「数据结构和算法」的过程中&#xff0c;因为人习惯了平铺直叙的思维方式&#xff0c;所以「递归」与「动态规划」这种带循环概念&#xff08;绕来绕去&#xff09;的往往是相对比较难以…