给定目标串 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】字符串匹配的更多相关文章

  1. 滑动窗口通用解leetcode字符串匹配问题

    滑动窗口,这玩意解决一些字符串匹配的题目是真的挺好用的,虽然本质还是双指针. 思路: 1.维护一个窗口,不断的向右边移动 2.满足要求后,移动左边,当不满足时,跳出. 3.重复1,2.得出答案. 下面 ...

  2. LeetCode 44 Wildcard Matching(字符串匹配问题)

    题目链接:https://leetcode.com/problems/wildcard-matching/?tab=Description   '?' Matches any single chara ...

  3. LeetCode 10 Regular Expression Matching(字符串匹配)

    题目链接 https://leetcode.com/problems/regular-expression-matching/?tab=Description   '.' Matches any si ...

  4. leetcode笔记 动态规划在字符串匹配中的应用

    目录 leetcode笔记 动态规划在字符串匹配中的应用 0 参考文献 1. [10. Regular Expression Matching] 1.1 题目 1.2 思路 && 解题 ...

  5. LeetCode 942. 增减字符串匹配(DI String Match) 49

    942. 增减字符串匹配 942. DI String Match 题目描述 每日一算法2019/6/21Day 49LeetCode942. DI String Match Java 实现 and ...

  6. LeetCode 686. 重复叠加字符串匹配(Repeated String Match)

    686. 重复叠加字符串匹配 686. Repeated String Match 题目描述 给定两个字符串 A 和 B,寻找重复叠加字符串 A 的最小次数,使得字符串 B 成为叠加后的字符串 A 的 ...

  7. Leetcode 686.重复叠加字符串匹配

    重复叠加字符串匹配 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd", ...

  8. Java实现 LeetCode 686 重复叠加字符串匹配

    686. 重复叠加字符串匹配 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd&q ...

  9. 字符串匹配KMP算法详解

    1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...

  10. 快速字符串匹配一: 看毛片算法(KMP)

    前言 由于需要做一个快速匹配敏感关键词的服务,为了提供一个高效,准确,低能耗的关键词匹配服务,我进行了漫长的探索.这里把过程记录成系列博客,供大家参考. 在一开始,接收到快速敏感词匹配时,我就想到了 ...

随机推荐

  1. js判断数字、整数、字符串、布尔,特殊方法

    整数: function isInteger(obj) { return Math.floor(obj) === obj } isInteger(3) // true isInteger(3.3) / ...

  2. 关于jQ的Ajax操作

    jQ的Ajax操作 什么是AJAX AJAX = 异步的javascript和XML(Asynchronous Javascript and XML) 它不是一门编程语言,而是利用JavaScript ...

  3. HTML基本内容

    设置背景色:<body bgcolor="#AAAAAA">,设置背景图:<body background="1.png">. 颜色的知 ...

  4. 【转】myeclipse 自定义视图Customize Perspective 没有反应

    官网查了下,解释如下:   附上链接https://www.myeclipseide.com/PNphpBB2-viewtopic-t-30151.html,大概意思是按如下图所示步骤更新即可.读者可 ...

  5. layer 弹出层 回调函数调用 弹出层页面 函数

    1.项目中用到layer 弹出层,定义一个公用的窗口,问题来了窗口弹出来了,如何保存页面上的数据呢?疯狂百度之后,有了结果,赶紧记下. 2.自己定义的公共页面方法: layuiWindow: func ...

  6. webservice跨域问题

    在webconfig里面加上   <httpProtocol>      <customHeaders>        <add name="Access-Co ...

  7. 2017"百度之星"程序设计大赛 - 复赛 01,03,05

    Arithmetic of Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  8. CAS 是什么

    CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换. CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B. 更新一个变量的时候,只有当变量的预期值 ...

  9. Java中 Tomcat 是干什么的?

    Tomcat是web容器.它的作用稍后给你解释. 你在做web项目时,多数需要http协议,也就是基于请求和响应,比如你在百度输入一行内容搜索, 那么百度服务器如何处理这个请求呢,他需要创建servl ...

  10. nodejs中function*、yield和Promise的示例

    var co = require("co"); var fs = require("fs"); function cusReadFile(fileName) { ...