目录
28. 找出字符串中第一个匹配项的下标
给你两个字符串
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 <= 10(4)
haystack
和needle
仅由小写英文字符组成
string内置函数find
1.
string类内置方法find,str.find(match)作用是在str内部寻找与match相匹配的子串,默认从0开始寻找。
str.find(match,5)作用是在str内部寻找与match相匹配的子串,从下标5开始寻找。
class Solution {
public:
int strStr(string haystack, string needle) {
return haystack.find(needle);
}
};
暴力枚举
1.
如果不用内置函数,暴力遍历,时间复杂度O(O*M)。
2. if (needle.size() > haystack.size())
return -1;
如果模式串的长度大于匹配串,不可能找到,直接返回-1。
3. for (int i = 0; i < haystack.size(); i++) {
遍历所有开始匹配的位置,从这个位置开始匹配。
4. int j = i;
int k = 0;
while (j < haystack.size() && k < needle.size() &&
haystack[j] == needle[k]) {
j++, k++;
}
如果退出循环,k指针遍历完所有的元素,此时表示找到了,返回j-k。 if (k == needle.size())
return j - k;
}
否则返回-1.表示没有找到。 return -1;
}
};
class Solution {
public:
int strStr(string haystack, string needle) {
if (needle.size() > haystack.size())
return -1;
for (int i = 0; i < haystack.size(); i++) {
int j = i;
int k = 0;
while (j < haystack.size() && k < needle.size() &&
haystack[j] == needle[k]) {
j++, k++;
}
if (k == needle.size())
return j - k;
}
return -1;
}
};
KMP算法
1.
KMP算法,时间复杂度O(N)。
主逻辑
2.
主函数内部逻辑,定义x,y双指针模拟匹配串和模式串的当前匹配下标。
x指针不回退,y指针回退。
x指针是匹配串的当前匹配下标。
y指针是模式串当前匹配下标。
3.
如果当前x,y位置匹配,x++,y++。
4.
如果当前x,y位置不匹配,选择y回退,y回退到next[y]位置。
即y=next[y]。
5.
当需要执行y=next[y]这条语句的时候,需要保证next[y]!=-1,也就是需要保证y!=0。
6.
如果y==0,此时x直接++,此时的x和y正好是下一个位置开始匹配的位置。
next逻辑
7.
人为规定,next[0]=-1,next[1]=0。
8.
一开始while里面cn为next[i-1],这是默认的但是不能显示赋值,如果显示赋值那么cn不会发生改变,会一直等于next[i-1],所以我们需要控制cn每次计算新的i需要等于next[i-1]。
9.
如果match[cn]==match[i-1],next[i]=cn+1。i++,cn=cn+1。
10.
如果match[cn]!=match[i-1],cn=next[cn]。
11.
需要执行cn=next[cn]这条语句,需要保证next[cn]!=-1,也就是cn!=0。
12.
如果cn==0还不匹配,next[i]=0。
class Solution {
public:
int strStr(string haystack, string needle) {
if (needle.size() > haystack.size())
return -1;
vector<int> next = getNext(needle);
int x = 0, y = 0;
while (x < haystack.size() && y < needle.size()) {
if (haystack[x] == needle[y]) {
x++, y++;
} else if (y != 0) {
y = next[y];
} else {
x++;
}
}
if (y == needle.size())
return x - y;
else
return -1;
}
vector<int> getNext(string match) {
if (match.size() == 1)
return {-1};
vector<int> next(match.size());
next[0] = -1, next[1] = 0;
int i = 2;
int cn = 0;
while (i < next.size()) {
if (match[cn] == match[i - 1]) {
next[i++] = ++cn;
} else if (cn != 0) {
cn = next[cn];
} else {
next[i++] = 0;
}
}
return next;
}
};
1408. 数组中的字符串匹配
给你一个字符串数组
words
,数组中的每个字符串都可以看作是一个单词。请你按 任意 顺序返回words
中是其他单词的子字符串的所有单词。如果你可以删除
words[j]
最左侧和/或最右侧的若干字符得到words[i]
,那么字符串words[i]
就是words[j]
的一个子字符串。示例 1:
输入:words = ["mass","as","hero","superhero"] 输出:["as","hero"] 解释:"as" 是 "mass" 的子字符串,"hero" 是 "superhero" 的子字符串。 ["hero","as"] 也是有效的答案。
示例 2:
输入:words = ["leetcode","et","code"] 输出:["et","code"] 解释:"et" 和 "code" 都是 "leetcode" 的子字符串。
示例 3:
输入:words = ["blue","green","bu"] 输出:[]
提示:
1 <= words.length <= 100
1 <= words[i].length <= 30
words[i]
仅包含小写英文字母。题目数据 保证 每个
words[i]
都是独一无二的。
string内置函数find
class Solution {
public:
vector<string> stringMatching(vector<string>& words) {
vector<string> ret;
for (int i = 0; i < words.size(); i++) {
for (int j = 0; j < words.size(); j++) {
if (i != j && words[j].find(words[i]) != string::npos) {
ret.push_back(words[i]);
break;
}
}
}
return ret;
}
};
KMP算法
class Solution {
public:
vector<string> stringMatching(vector<string>& words) {
vector<string> ret;
for (int i = 0; i < words.size(); i++) {
for (int j = 0; j < words.size(); j++) {
if (i != j && strStr(words[j], words[i])) {
ret.push_back(words[i]);
break;
}
}
}
return ret;
}
bool strStr(string haystack, string needle) {
if (needle.size() > haystack.size())
return false;
vector<int> next = getNext(needle);
int x = 0, y = 0;
while (x < haystack.size() && y < needle.size()) {
if (haystack[x] == needle[y]) {
x++, y++;
} else if (y != 0) {
y = next[y];
} else {
x++;
}
}
if (y == needle.size())
return true;
else
return false;
}
vector<int> getNext(string match) {
if (match.size() == 1)
return {-1};
vector<int> next(match.size());
next[0] = -1, next[1] = 0;
int i = 2;
int cn = 0;
while (i < next.size()) {
if (match[cn] == match[i - 1]) {
next[i++] = ++cn;
} else if (cn != 0) {
cn = next[cn];
} else {
next[i++] = 0;
}
}
return next;
}
};
1455. 检查单词是否为句中其他单词的前缀
给你一个字符串
sentence
作为句子并指定检索词为searchWord
,其中句子由若干用 单个空格 分隔的单词组成。请你检查检索词searchWord
是否为句子sentence
中任意单词的前缀。如果
searchWord
是某一个单词的前缀,则返回句子sentence
中该单词所对应的下标(下标从 1 开始)。如果searchWord
是多个单词的前缀,则返回匹配的第一个单词的下标(最小下标)。如果searchWord
不是任何单词的前缀,则返回-1
。字符串
s
的 前缀 是s
的任何前导连续子字符串。示例 1:
输入:sentence = "i love eating burger", searchWord = "burg" 输出:4 解释:"burg" 是 "burger" 的前缀,而 "burger" 是句子中第 4 个单词。
示例 2:
输入:sentence = "this problem is an easy problem", searchWord = "pro" 输出:2 解释:"pro" 是 "problem" 的前缀,而 "problem" 是句子中第 2 个也是第 6 个单词,但是应该返回最小下标 2 。
示例 3:
输入:sentence = "i am tired", searchWord = "you" 输出:-1 解释:"you" 不是句子中任何单词的前缀。
提示:
1 <= sentence.length <= 100
1 <= searchWord.length <= 10
sentence
由小写英文字母和空格组成。
searchWord
由小写英文字母组成。
1.
利用双指针分割所有的单词,装到words数组中。
2.
定义cur指向当前单词的首字母,pos查找当前单词后面出现的空格。
3.
如果找到了空格,说明这个单词不是最后一个出现的单词。
4.
单词的长度是pos-cur,获取sentence的子串,利用内置函数substr(cur,length),从cur位置开始往后长度为length的子串。
5.
获取此时单词后,维护cur=pos+1,表示下一个单词的首字母位置。
6.
pos=pos+1,表示下一个空格开始寻找的位置。
7.
如果从pos位置开始查找找不到空格,说明此时是最后一个单词。
8.
直接获取cur位置到结尾的子串即可。
class Solution {
public:
int isPrefixOfWord(string sentence, string searchWord) {
vector<string> words;
int pos = 0;
int cur = 0;
while (1) {
pos = sentence.find(" ", pos);
if (pos != string::npos) {
int length = pos - cur;
words.push_back(sentence.substr(cur, length));
cur = pos + 1;
pos++;
} else {
words.push_back(sentence.substr(cur));
break;
}
}
// for(auto x:words){
// cout<<x<<" ";
// }
for (int i = 0; i < words.size(); i++) {
if (words[i].substr(0, searchWord.size()) == searchWord) {
return i + 1;
}
}
return -1;
}
};
结尾
最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。
同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。
谢谢您的支持,期待与您在下一篇文章中再次相遇!