摘要:
Leetcode的AC指南 —— 字符串/KMP:28.找出字符串中第一个匹配项的下标。题目介绍:给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
文章目录
- 一、题目
- 二、解析(go)
- 1、一个简单的AC方法
- 2、KMP算法:直接使用前缀表作为next数组
- 三、其他语言版本
- Java
- C++
- Python
题目介绍:给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
力扣题目链接
示例 1:
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
示例 2:
输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
提示:
1 <= haystack.length, needle.length <= 104
haystack 和 needle 仅由小写英文字符组成
思路:让needle在haystack中滑动
go:
func strStr(haystack string, needle string) int {
runes := []byte(haystack)
for i := 0; i <= len(haystack)-len(needle); i++ {
if string(runes[i:len(needle)+i]) == needle {
return i
}
}
return -1
}
思路:
构造next数组
使用next数组做匹配
//直接将前缀表作为next数组
func getnext(next []int, s string) {
// before: 前缀末尾,前缀长度
// behand:后缀末尾
before := 0
next[0] = 0
for behind := 1; behind < len(s); behind++ {
for before > 0 && s[behind] != s[before] { // 前缀与后缀不相等
before = next[befor-1]
}
if s[behind] == s[before] { // 前缀与后缀相等
before++
}
next[behind] = before
}
}
// 直接将前缀表作为next数组的匹配实现
func strStr(haystack string, needle string) int {
j := 0 // j 为模式串的起始位置, next数组记录的起始位置为0
next := make([]int, len(needle))
getnext(next, needle)
for i := 0; i < len(haystack); i++ { // i从0开始
for j > 0 && haystack[i] != needle[j] { // 不匹配
j = next[j-1] // j寻找之前匹配的位置
}
if haystack[i] == needle[j] { // 匹配,j 和 i同时向后移动
j++ // i的增加在for循环中
}
if j == len(needle) { // 文本串haystack中出现了模式串needle
return i - j + 1
}
}
return -1
}
class Solution {
//前缀表(不减一)Java实现
public int strStr(String haystack, String needle) {
if (needle.length() == 0) return 0;
int[] next = new int[needle.length()];
getNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
while (j > 0 && needle.charAt(j) != haystack.charAt(i))
j = next[j - 1];
if (needle.charAt(j) == haystack.charAt(i))
j++;
if (j == needle.length())
return i - needle.length() + 1;
}
return -1;
}
private void getNext(int[] next, String s) {
int j = 0;
next[0] = 0;
for (int i = 1; i < s.length(); i++) {
while (j > 0 && s.charAt(j) != s.charAt(i))
j = next[j - 1];
if (s.charAt(j) == s.charAt(i))
j++;
next[i] = j;
}
}
}
class Solution {
public:
void getNext(int* next, const string& s) {
int j = 0;
next[0] = 0;
for(int i = 1; i < s.size(); i++) {
while (j > 0 && s[i] != s[j]) {
j = next[j - 1];
}
if (s[i] == s[j]) {
j++;
}
next[i] = j;
}
}
int strStr(string haystack, string needle) {
if (needle.size() == 0) {
return 0;
}
int next[needle.size()];
getNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.size(); i++) {
while(j > 0 && haystack[i] != needle[j]) {
j = next[j - 1];
}
if (haystack[i] == needle[j]) {
j++;
}
if (j == needle.size() ) {
return (i - needle.size() + 1);
}
}
return -1;
}
};
class Solution:
def getNext(self, next: List[int], s: str) -> None:
j = 0
next[0] = 0
for i in range(1, len(s)):
while j > 0 and s[i] != s[j]:
j = next[j - 1]
if s[i] == s[j]:
j += 1
next[i] = j
def strStr(self, haystack: str, needle: str) -> int:
if len(needle) == 0:
return 0
next = [0] * len(needle)
self.getNext(next, needle)
j = 0
for i in range(len(haystack)):
while j > 0 and haystack[i] != needle[j]:
j = next[j - 1]
if haystack[i] == needle[j]:
j += 1
if j == len(needle):
return i - len(needle) + 1
return -1