【LeetCode】字符串匹配
给定目标串 haystack 和模式串 needle ,返回 needle 在 haystack 中第一次出现的位置下标,若 needle 不是 haystack 的子串则返回 -1。
1. Brute-Force Algorithm(暴力算法 / 简单模式匹配)
我自己写了一种双层循环的
int strStr(string haystack, string needle) {
if (needle.empty()) return ;
int m = haystack.size(), n = needle.size();
for (int i = ; i <= m - n; i++) {
for (int j = ; j < n; j++) {
if (needle[j] != haystack[i + j])
break;
if (j == n - )
return i;
}
}
return -;
}
看了答案发现了一种更高效的方法,虽然时间复杂度同样是 O(m*n),但只要一层循环,非常Nice!
int strStr(string haystack, string needle) {
if (needle.empty()) return ;
int i = , j = ;
int m = haystack.size(), n = needle.size();
while (i < m && j < n) {
if (haystack[i] == needle[j]) {
i++;
j++;
} else {
i = i - j + ;
j = ;
}
if (j == n)
return i - j;
}
return -;
}
2. KMP算法
算法讲解可以参考 http://www.61mon.com/index.php/archives/183/ ,讲解的已经很好了。
KMP的时间复杂度仅为 O(m+n),因为当出现子串与主串某处不匹配时,并不会将遍历主串的下标 i 回溯,而是利用得到的 next 数组将模式子串向右“滑动”尽可能远的一段距离,继续进行比较,提高了效率。
next 数组的求解是关键,它是基于模式子串的最长前后缀,next[i] = needle[0] 到 needle[i - 1] 的字符串的最长相同前后缀的长度。
void getNext(string needle, vector<int> &next) {
int i = , j = -;
// j 表示最长相同前后缀的长度
next[] = j;
while (i < needle.size()) {
// j == -1 为边界条件判断, j = next[j] 可能使 j 退回到 -1
if (j == - || needle[i] == needle[j]) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
}
int strStr(string haystack, string needle) {
if (needle.empty()) return ;
int i = , j = ;
int m = haystack.size(), n = needle.size();
vector<int> next(n + );
getNext(needle, next);
while (i < m && j < n) {
if (j == - || haystack[i] == needle[j]) {
i++;
j++;
} else {
j = next[j];
}
if (j == n)
return i - j;
}
return -;
}
改进的KMP算法
void getNextval(string needle, vector<int> &nextval) {
int i = , j = -;
nextval[] = j;
while (i < needle.size()) {
if (j == - || needle[i] == needle[j]) {
i++;
j++;
// 生成 nextval 数组
if (needle[i] != needle[j])
nextval[i] = j;
else
nextval[i] = nextval[j];
} else {
j = nextval[j];
}
}
}
int strStr(string haystack, string needle) {
if (needle.empty()) return ;
int i = , j = ;
int m = haystack.size(), n = needle.size();
vector<int> nextval(n + );
getNextval(needle, nextval);
while (i < m && j < n) {
if (j == - || haystack[i] == needle[j]) {
i++;
j++;
} else {
j = nextval[j];
}
if (j == n)
return i - j;
}
return -;
}
【LeetCode】字符串匹配的更多相关文章
- 滑动窗口通用解leetcode字符串匹配问题
滑动窗口,这玩意解决一些字符串匹配的题目是真的挺好用的,虽然本质还是双指针. 思路: 1.维护一个窗口,不断的向右边移动 2.满足要求后,移动左边,当不满足时,跳出. 3.重复1,2.得出答案. 下面 ...
- LeetCode 44 Wildcard Matching(字符串匹配问题)
题目链接:https://leetcode.com/problems/wildcard-matching/?tab=Description '?' Matches any single chara ...
- LeetCode 10 Regular Expression Matching(字符串匹配)
题目链接 https://leetcode.com/problems/regular-expression-matching/?tab=Description '.' Matches any si ...
- leetcode笔记 动态规划在字符串匹配中的应用
目录 leetcode笔记 动态规划在字符串匹配中的应用 0 参考文献 1. [10. Regular Expression Matching] 1.1 题目 1.2 思路 && 解题 ...
- LeetCode 942. 增减字符串匹配(DI String Match) 49
942. 增减字符串匹配 942. DI String Match 题目描述 每日一算法2019/6/21Day 49LeetCode942. DI String Match Java 实现 and ...
- LeetCode 686. 重复叠加字符串匹配(Repeated String Match)
686. 重复叠加字符串匹配 686. Repeated String Match 题目描述 给定两个字符串 A 和 B,寻找重复叠加字符串 A 的最小次数,使得字符串 B 成为叠加后的字符串 A 的 ...
- Leetcode 686.重复叠加字符串匹配
重复叠加字符串匹配 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd", ...
- Java实现 LeetCode 686 重复叠加字符串匹配
686. 重复叠加字符串匹配 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd&q ...
- 字符串匹配KMP算法详解
1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...
- 快速字符串匹配一: 看毛片算法(KMP)
前言 由于需要做一个快速匹配敏感关键词的服务,为了提供一个高效,准确,低能耗的关键词匹配服务,我进行了漫长的探索.这里把过程记录成系列博客,供大家参考. 在一开始,接收到快速敏感词匹配时,我就想到了 ...
随机推荐
- centos7 修改密码
Centos7破解密码的方法 Centos7忘记密码 在工作或者自己练习的时候我们难免会大意忘掉自己的root密码,有些同学忘掉密码竟然第一选择是重装系统,工作中可万万使不得! 本篇博客将讲解 ...
- springmvc通过ajax异步请求返回json格式数据
jsp 首先创建index.jsp页面 <script type="text/javascript"> $(function () { $("#usernam ...
- bean的实例化有几种实现方式
三种实例化bean的方式 在spring中有三中实例化bean的方式: 一.使用构造器实例化:(90%通常使用的一个方法) 二.使用静态工厂方法实例化: 三.使用实例化工厂方法实例化. 每种实例化 ...
- JsonKey小写
System.Text.RegularExpressions.MatchCollection ms = System.Text.RegularExpressions.Regex.Matches(eca ...
- dplyr-高效的数据变换与整理工具--转载
1.背景简介 在数据分析工作中,经常需要对原始的数据集进行清洗.整理以及变换.常用的数据整理与变换工作主要包括:特定分析变量的选取.满足条件的数据记录的筛选.按某一个或几个变量排序.对原始变量进行加工 ...
- 简单Promise回顾
1:传统的CallBack回调函数let ajax=function(callback){ //dosomething this.setTimeout(()=>{ callback&&a ...
- Java Virtual Machine(Java虚拟机)
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的. Java语言 ...
- Oracle简介
1.Oracle 数据库基于客户端/服务 2. Oracle认证 OCA:Oracle认证助理工程师,比较简单 OCP:Oracle认证专家 OCM:Oracle认证资深专家 3.Oracle 服务的 ...
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...
- 几种RAID介绍(总结)
概念 RAID是Redundent Array of Inexpensive Disks的缩写,简称为“磁盘阵列”.后来RAID中的字母I被改作了Independent,RAID就成了“独立冗余磁盘阵 ...