刷题记录Day9-字符串(KMP算法)
前言
题目来源:leetcode
刷题顺序:代码随想录
刷题工具:VSCode+leetcode插件
补充:延毕时间充裕,会结合LeetCode 101: A LeetCode Grinding Guide (C++ Version)相似题目一起做。
KMP算法
KMP主要应用在字符串匹配上。
KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。
算法思路的学习参考:实现strStr()
一、找出字符串中第一个匹配项的下标
1. 28找出字符串中第一个匹配项的下标
题目:
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
示例:
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
代码:
class Solution {
public:
void getNext(int* next, const string& s){
int j =0;
next[0] = j;
for (int i =1; i<s.size(); ++i){
while (j>0 && s[j] != s[i]){
j = next[j-1];
}
if (s[j] == s[i]){
++j;
}
next[i] = j;
}
}
int strStr(string haystack, string needle) {
int next[needle.size()];
getNext(next,needle);
int j =0;
for (int i =0; i<haystack.size(); ++i){
while (j>0 && needle[j] !=haystack[i]){
j = next[j-1];
}
if(needle[j] == haystack[i]){
++j;
}
if (j == needle.size()){
return i-j+1;
}
}
return -1;
}
};
看了一边视频之后自己实现的,能够理解。
2. 459重复的子字符串
题目:
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
示例:
输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。
代码:
方法一,kmp算法,还可以再理解一下
class Solution {
public:
void getNext(int* next, const string& s){
int j =0;
next[0] = j;
for (int i =1; i<s.size(); ++i){
while (j>0 && s[j]!=s[i]){
j = next[j-1];
}
if (s[j] == s[i]){
++j;
}
next[i] = j;
}
}
bool repeatedSubstringPattern(string s) {
int next[s.size()];
getNext(next,s);
int count = next[s.size()-1];
return count!=0 && s.size()%(s.size()-count) ==0;
}
};
方法二,太巧妙了,想不到
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string t = s + s;
t.erase(t.begin()); t.erase(t.end() - 1); // 掐头去尾
if (t.find(s) != std::string::npos) return true; // r
return false;
}
};
总结
kmp算法想通了,但用来做题还是有点吃力。感觉还是要多多看。