字符串的匹配先定义两个名词:模式串和文本串。我们的任务就是在文本串中找到模式串第一次出现的位置,如果找到就返回位置的下标,如果没有找到返回-1.其实这就是C++语言里面的一个函数:

extern char *strstr(char *str1, const char *str2);

对于这个函数的解释:

str1: 被查找目标
str2: 要查找对象
返回值:如果str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。
例如:
char str[]="1234xyz";
char *str1=strstr(str,"34");
cout << str1 << endl;
显示的是: 34xyz

  返回值是一个指针,这个指针指向文本串中第一次出现模式串的位置。


字符串查找的暴力算法

先看LeetCode上的一道题目,实现这个函数 int strStr(string haystack, string needle); ,要求返回文本串中出现模式串的下标值。

1.如果模式串为NULL,那么直接返回0.
2.如果模式串的长度大于文本串,那么一定查找不到,返回-1.
3.如果存在的话,查找的范围可以限定在文本串的0~s.size()-p.size();

所以暴力算法的代码实现:

int strStr(string haystack, string needle)
{int i = 0;//模式串为空if(needle.empty()){return 0;}//文本串的大小小于模式串if(haystack.size() < needle.size()){return -1;}//确定查找的范围for(i = 0; i <= haystack.size()-needle.size(); ++i){int j = 0;for(j = 0; j < needle.size(); ++j){if(haystack[i+j] != needle[j]){break;}}//forif(j == needle.size()){return i;}}//forif(i == haystack.size()-needle.size() + 1){return -1;}
}

字符串查找的KMP算法

上面的暴力算法,在查找失败以后都要进行回溯,下面再给出一个版本,明显的看到i,j的回溯:

int strStr(string haystack, string needle)
{int sLen = haystack.size();int pLen = needle.size();int i = 0;int j = 0;while(i < sLen && j < pLen){if(haystack[i] == needle[j]){++i;++j;}else{i = i - j + 1;j = 0;}}//whileif(j == pLen){return i - j;}else{return -1;}
}

假设我们已经知道了KMP的next数组,所以每次失配以后,i不回溯,j回溯到next[j]指定的位置。也就是 j = next[j]; 。

int KmpSearch(char *s, char *p)
{int i = 0;int j = 0;int sLen = strlen(s);int pLen = strlen(p);while(i < sLen && j < pLen){//如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++if(j == -1 || s[i] == p[j]){i++;j++;}else{//如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]     //next[j]即为j所对应的next值j = next[j];}}//whileif(j == pLen){return i - j;}else{return -1;}
}

对于上面的j=-1和next[0]=-1作下面的解释:

说完了KMP的大的框架,下面就得说一下next数组的求解过程了:  

void GetNext(char *p, int *next)
{int pLen = strlen(p);int j = 0;int k = -1;next[0] = -1;while(j < pLen - 1){//p[k]表示前缀,p[j]表示后缀if(k == -1 || p[j] == p[k]){++k;++j;next[j] = k;//表示在j这个字符之前,能够构成公共前后缀的最大字符数}else{k = next[k];//回溯之前已经有过匹配的前缀}}
}

  

KMP算法的一个改进  

上面的KMP算法已经能够很好的跑出结果来了,但是还可以改进,看下面的一个字符串的匹配:

改进的代码实现:

void GetNextVal(char *p, int *next)
{int pLen = strlen(p);int j = 0;int k = -1;next[0] = -1;while(j < pLen - 1){//p[k]表示前缀,p[j]表示后缀if(k == -1 || p[j] == p[k]){++k;++j;if(p[j] != p[k]){next[j] = k;//表示在j这个字符之前,能够构成公共前后缀的最大字符数}else{next[j] = next[k];//因为不能出现p[j] = p[next[j]],所以当出现时需要继续递归,k = next[k] = next[next[k]]}}else{k = next[k];//回溯之前已经有过匹配的前缀}}
}

再来看一个极端的情况:

  

转载于:https://www.cnblogs.com/stemon/p/4851524.html

从C++strStr到字符串匹配算法相关推荐

  1. KMP、BM、Sunday、Horspool、strstr字符串匹配算法的性能比较

    KMP.BM.Sunday.Horspool.strstr字符串匹配算法的性能比较 一.简介 简介:字符串匹配算法,顾名思义,在一个给定的字符文本内搜寻出自己想要找的一个字符串,平常所用的各种文本编辑 ...

  2. 字符串匹配算法(KMP)

    文章目录 1. KMP由来 2. KMP算法基本原理 3. 代码 4. Leetcode 28. 实现 strStr() 1. KMP由来 上一节说的BM算法是最高效.最常用的字符串匹配算法. 最知名 ...

  3. 字符串匹配KMP算法设计C语言,KMP字符串匹配算法笔记

    网上有很多解释KMP算法的文章,A_B_C_ABC的这篇很详细,反复看了好几遍,总算理解了个大概,但是总觉得没那么爽快.其实,一种算法各人有各人的理解方法,找到适合自己理解的才容易记住.下面是我对这个 ...

  4. String Matching 字符串匹配算法——干货从头放到尾

    需要的先验知识:动态规划,有限状态机,搜索算法(就是含有state,action和policy)的模型,java.上面这些不需要知道很细,大概懂这些都是啥就可以读懂本文. 写这篇技术博客的动机是因为做 ...

  5. c++ 字符串匹配算法sunday算法

    sunday 算法是一种很高效的字符串匹配算法, 其实现也较kmp算法简单很多 class Sunday {public:const string& needle;int mp[300];Su ...

  6. 字符串匹配算法之Sunday算法

    字符串匹配查找算法中,最着名的两个是KMP算法(Knuth-Morris-Pratt)和BM算法(Boyer-Moore).两个算法在最坏情况下均具有线性的查找时间.但是在实用上,KMP算法并不比最简 ...

  7. 字符串匹配算法之暴力做法(朴素算法)

    字符串匹配算法之暴力做法(朴素算法) 1.字符串匹配算法 1.1 简介 1.2 类型 1.3 示例题目 2.暴力做法(朴素算法) 2.1 暴力算法的思路 2.2 暴力算法的特点: 2.3 暴力算法的J ...

  8. 数据结构与算法分析(十六)--- 如何设计更高效的字符串匹配算法?(BF + RK + KMP + BMH)

    文章目录 一.Brute Force 匹配算法 二.Rabin–Karp 匹配算法 三.Knuth–Morris–Pratt 匹配算法 四.Boyer-Moore-Horspool 匹配算法 五.字符 ...

  9. 字符串匹配算法(BF算法KMP算法)

    字符串匹配算法 暴力匹配(BF)算法 KMP算法 next数组 求next数组的练习 next数组的优化(nextval数组) 练习 暴力匹配(BF)算法 BF算法,即暴力(Brute Force)算 ...

最新文章

  1. Kubernetes上领先的开源Serverless解决方案有哪些
  2. 3W法—what,why,how的运用
  3. 高并发场景下的httpClient优化使用
  4. Linux的ps aux/ps -ef:风格不同
  5. webpack打包---报错内存溢出javaScript heap out of memory
  6. EAI的Spring集成教程
  7. array函数参数 scala_scala – 在Spark SQL中将数组作为UDF参数传递
  8. java 防止证书导出_如何把安全证书导入到java中的cacerts证书库
  9. [python机器学习及实践(2)]Sklearn实现朴素贝叶斯
  10. python简单文件服务器
  11. 计算机ppt基础知识题库,计算机二级考试MSOffice考试题库ppt操作题附答案.pdf
  12. 编写matlab程序设计状态反馈增益阵,利用MATLAB设计状态观测器.pdf
  13. 执行npm install报错:npm ERR! code EINTEGRITY,npm ERR! 最彻底,最实用的方法就是更新node版本
  14. 环境微生物学练习题及答案
  15. 基于SpringBoot的报刊订阅管理系统
  16. Mac键盘突然失灵怎么办?别急,教你打开辅助键盘
  17. 【计算机视觉算法岗面经】“吐血”整理:2019秋招资料
  18. 【Python爬虫】爬取豆瓣电影Top 250
  19. js使用moment获取当前日期是当前月的第几周
  20. 浏览器中的data类型的Url格式,data:image/png,data:image/jpeg!

热门文章

  1. python封装api linux_python Socket编程-python API 与 Linux Socket API之间的关系
  2. 5 select 选择的值_表单元素之选择类型
  3. 说一下你对多态的理解?_掌握了多态的特性,写英雄联盟的代码更少啦!
  4. mysql下载为csv_MySQL 查询结果保存为CSV文件
  5. 在FFT分析在而立之年的展望与总结
  6. BL1551模拟开关,封装SC70-6
  7. 2021年春季学期-信号与系统-第四次作业参考答案-第七小题
  8. python目标跟踪_商汤开源最大目标跟踪库PySOT,代码已正式上线!
  9. SHELL脚本 基础一
  10. 中国计算机专业专科学校排名2015,计算机专科学校排名前十(最出名的10所计算机学院)...