C++ 检查给定句子中子字符串S1是否出现在子字符串S2的任何出现之后
在这个问题中,我们需要检查子字符串S1是否出现在给定字符串S中子字符串S2的任何出现之后。我们可以比较字符串S中的S1和S2的起始索引来解决这个问题。
问题陈述: 我们给定了三个子字符串S、S1和S2。字符串S总是包含S1作为子字符串。我们需要检查子字符串S1是否出现在给定字符串S中子字符串S2的任何出现之后。
示例
输入: S = “abxtutorialspointwelcomepoint”,S1 = “welcome”,S2 = “point”;
输出: 是
解释: 在字符串S中,’point’子字符串出现了2次。一次在’welcome’之前,另一次在之后。因此,我们可以说字符串S1出现在字符串S2的任何出现之后。
输入: S = “abcdefgh”,S1 = “abcd”,S2 = “gh”;
输出: 否
解释: S1位于字符串S的开头。因此,S1在子字符串S2之后没有出现。
输入: S = “abce”,S1 = “bc”,S2 = “xy”;
输出: 否
解释: 由于字符串S2不在字符串S中,所以输出为“否”。
方法1
在这个方法中,我们将找到子字符串S2的所有起始索引,并将它们存储在集合中。然后,我们将获取子字符串S1的起始索引。我们将比较S2的每个起始索引和S1的起始索引,如果我们发现集合中的任何一个值小于S2的起始索引,我们可以说子字符串S1出现在子字符串S2的任何出现之后。
步骤
- 定义一个集合来存储子字符串S2的起始索引。
- 使用find()方法找到子字符串S2的第一个起始索引。
- 使用while循环获取子字符串S2的所有起始索引,并使用insert()方法将它们存储在集合中。
- 遍历集合的值。如果任何一个值小于给定字符串S中子字符串S1的起始索引,则返回true。
- 最后返回false。
示例
#include <iostream>
#include <string>
#include <unordered_set>
using namespace std;
bool isS1AfterS2(string& S, string& S1, string& S2) {
// set to store indices of S2 in S
unordered_set<int> indices;
// Find all occurrences of S2 in S, and store them in set
size_t found = S.find(S2);
while (found != string::npos) {
indices.insert(found);
found = S.find(S2, found + 1);
}
// Compare starting indices of S1 with S2
for (const int& index : indices) {
if (index < S.find(S1)) {
return true; // S2 appears before S1
}
}
return false; // S1 appears before or at the same position as S2
}
int main(){
string S = "abxtutorialspointwelcomepoint";
string S1 = "welcome", S2 = "point";
if(isS1AfterS2(S, S1, S2)) {
cout << "Yes, string S1 appears after string S2.";
} else {
cout << "No, string S1 does not appear after string S2.";
}
return 0;
}
输出
Yes, string S1 appears after string S2.
时间复杂度 – O(N*K),因为我们需要找到字符串S2的起始索引。
空间复杂度 – O(N),因为我们存储字符串S2的起始索引。
方法2
在这种方法中,我们将遍历字符串。如果我们在字符串S1之前找到了字符串S2的出现,则返回true,因为字符串S总是包含字符串S1。
步骤
- 定义len、n1和n2变量来存储变量的长度。
-
开始遍历字符串。
-
定义“temp字符串并将其初始化为从第i个索引开始的长度为n2的子字符串。
-
如果temp S2,则返回true。
-
从第i个索引开始取一个长度为n1的子字符串。如果temp s1,则返回false。
-
最后返回true。
示例
#include <bits/stdc++.h>
using namespace std;
bool isS1AfterS2(string &S, string &S1, string &S2){
// store the length of the strings
int n1 = S1.size(), n2 = S2.size();
// Traverse the string S from left to right
for (int i = 0; i <= S.size() - n2; i++){
// temporary string to store substring
string temp;
// get the substring
temp = S.substr(i, n2);
// if we find the string S2, return true as s1 always present in s.
if (temp == S2){
return true;
}
temp = S.substr(i, n1);
// If we find s1 before s2, return false
if (temp == S1){
return false;
}
}
return true;
}
int main(){
string S = "abxtutorialspointwelcome";
string S1 = "welcome", S2 = "point";
if(isS1AfterS2(S, S1, S2)) {
cout << "Yes, string S1 appears after string S2.";
} else {
cout << "No, string S1 does not appear after string S2.";
}
return 0;
}
输出
Yes, string S1 appears after string S2.
时间复杂度为O(N*min(n1, n2)),因为我们找到了长度为n1和n2的子字符串。
空间复杂度为O(min(n1, n2)),因为我们存储了子字符串。
在第一种方法中,我们使用集合来存储S2的起始索引,这需要比第二种方法更多的空间。第二种方法的代码比第一种更易读。此外,程序员们可以尝试解决检查子字符串S2是否出现在S1的任何位置之后的问题。