檢查給定句子中子字串 S1 是否出現在子字串 S2 的任何出現之後


在這個問題中,我們需要檢查子字串 S1 是否出現在給定字串 S 中子字串 S2 的任何出現之後。我們可以比較 S1 和 S2 在字串 S 中的起始索引來解決這個問題。

問題陳述 – 我們給出了三個名為 S、S1 和 S2 的子字串。字串 S 始終包含 S1 作為子字串。我們需要檢查子字串 S1 是否出現在給定字串 S 中子字串 S2 的任何出現之後。

示例

輸入 – S = "abxtutorialspointwelcomepoint",S1 = "welcome",S2 = "point";

輸出 – 是

解釋 – 在字串 S 中,“point”子字串出現 2 次。一個在“welcome”之前,另一個在“welcome”之後。所以,我們可以說字串 S1 出現在字串 S2 的任何出現之後。

輸入 – S = "abcdefgh",S1 = "abcd",S2 = "gh";

輸出 – 否

解釋 S1 位於字串 S 的開頭。因此,S1 不出現在子字串 S2 之後。

輸入 – S = "abce",S1 = "bc",S2 = "xy";

輸出 – 否

解釋 – 由於字串 S2 不存在於字串 S 中,因此輸出為否。

方法一

在這種方法中,我們將找到所有 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 的起始索引。

方法二

在這種方法中,我們將遍歷字串。如果我們在 S1 出現之前找到 S2 的出現,我們將返回 true,因為字串 S 始終包含字串 S1。

演算法

  • 定義 len、n1 和 n2 變數來儲存變數的長度。

  • 開始遍歷字串。

  • 定義“臨時字串”並將其初始化為從第 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 的任何出現之後的問題。

更新於:2023年8月17日

237 次瀏覽

開啟你的職業生涯

完成課程獲得認證

開始
廣告