C++ 至少包含前K个字母的子字符串数量

C++ 至少包含前K个字母的子字符串数量

在这个问题中,我们需要计算至少包含所有K个字符中每个字符至少1次出现的子字符串。

这里,我们将使用两种不同的方法来解决这个问题。第一种方法是获取给定字符串的所有子字符串,检查子字符串是否包含所有K个字符,并计算包含所有K个字符的子字符串数量。

第二种方法使用滑动窗口技术来解决这个问题。

问题陈述 - 我们给定一个包含N个字符的字符串alpha。同时,我们给定K,表示只包含前K个字母字符的字符串。我们需要计算总共包含至少1次所有K个字符的子字符串数量。

示例示例

输入

alpha = "abcdda", K = 4;

输出

4

解释 - 包含所有4个字符的子字符串是’abcd’、’abcdd’、’abcdda’和’bcdda’。

输入

alpha = "abc", K = 5

输出

0

说明 - 给定的字符串中没有包含所有5个字符的子字符串。

输入

alpha = "ccbba"; K = 3;

输出

2

解释 - 字符串’ccbba’和’cbba’包含所有3个字符。

方法1

在这个方法中,我们将遍历字符串以获取所有子字符串,并将它们存储在列表中。之后,我们将从字符串列表中计算至少包含所有K个字符一次的字符串的数量。

算法

步骤1 - 初始化’subStr’列表以存储所有子字符串。

步骤2 - 开始遍历字符串。同时,使用嵌套循环从1到字符串大小-p进行迭代。

步骤3 - 使用substr()方法从第p个索引开始获取长度为q的子字符串。同时,将子字符串推到’subStr’列表中。

步骤4 - 初始化’result’为0,用于存储有效子字符串的计数。

步骤5 - 开始遍历子字符串列表,并定义’freq’映射以存储当前字符串中字符的频率。同时,将’chars’初始化为0,用于计算字符串中的不同字符数。

步骤6 - 开始遍历当前字符串。如果映射中字符的频率为0,则更新频率,并将’chars’的值加1。

步骤7 - 如果chars的值等于K,则将’result’增加1。

步骤8 - 返回’result’的值。

示例

#include <bits/stdc++.h>
using namespace std;

int numberOfSubstrings(string alpha, int K) {
   // Finding all substrings of the alpha
   vector<string> subStr;
   for (int p = 0; p < alpha.size(); p++) {
      for (int q = 1; q <= alpha.size() - p; q++) {
         // Get substring from p to q
         subStr.push_back(alpha.substr(p, q));
      }
   }
   // Counting the number of substrings containing all K characters
   int result = 0;
   for (int p = 0; p < subStr.size(); p++) {
      // To store the frequency of characters in the current substring
      map<char, int> freq;
      // To store the totally different characters
      int chars = 0;
      // Traverse substring
      for (int q = 0; q < subStr[p].size(); q++) {
         // If a character does not exist in the map, increment chars
         if (freq[subStr[p][q]] == 0) {
            freq[subStr[p][q]]++;
            chars++;
         }
      }
      // If different chars are the same as K, the string is valid.
      if (chars == K) {
         result++;
      }
   }
   return result;
}
int main() {
   string alpha = "abcdda";
   int K = 4;
   cout << "The number of substrings containing all K characters at least once is " << numberOfSubstrings(alpha, K);
   return 0;
}

输出

The number of substrings containing all K characters at least once is 4

时间复杂度 – O(NNM),其中O(N*N)是获取所有子字符串的时间复杂度,O(M)是遍历字符串的时间复杂度。

空间复杂度 – O(N*N)用于存储所有子字符串。

第二种方法

在这种方法中,我们将使用滑动窗口技术来计算至少包含所有K个字符的子字符串的数量。

算法

第一步 - 初始化“freq”映射以存储字符频率,“left”和“right”指针为0,表示滑动窗口指针,“len”为字符串长度,并将“cnt”初始化为0以存储字符串的数量。

第二步 - 迭代直到“right”小于字符串长度为止。

第三步 - 增加映射中“right”索引处的字符的频率。

第四步 - 如果映射的大小等于K,表示我们找到了包含所有K个字符的子字符串。执行以下步骤。

第四步.1 - 迭代直到映射的大小等于K。

第四步.2 - 将“len – right”添加到“cnt”中。

第四步.3 - 从当前窗口中移除左边的字符,在映射中减小它的频率。如果映射中的字符频率为0,则从映射中删除该字符。

第四步.4 - 在嵌套循环中增加“left”指针。

第四步.5 - 在主循环中增加“right”指针。

第五步 - 否则,增加“right”指针的值。

第六步 - 返回“cnt”的值。

例子

让我们通过示例输入来理解滑动窗口技术如何解决该问题。

输入 – ‘abcdaabc’,K = 4

  • 第一个窗口将是包含所有4个字符的’abcd’。因此,我们可以说(0, 3),(0, 4),(0, 5),(0, 6)和(0, 7)所有的子字符串至少包含所有K个字符。

  • 之后,从1到4的下一个窗口包含所有的字符。所以,(1, 4),(1,5),(1, 6)和(1, 7)所有的子字符串至少包含所有的K个字符一次。

  • 这样,我们可以计算每个有效窗口的子字符串数量。

#include <bits/stdc++.h>
using namespace std;

int numberOfSubstrings(string alpha, int K) {
   // For storing the frequency of characters
   unordered_map<char, int> freq;
   int left = 0, right = 0, len = alpha.size(), cnt = 0;
   // Traveres the string
   while (right < len) {
     // Update character frequency
     freq[alpha[right]]++;
     // If the size of the map contains all K characters
     if (freq.size() == K) {
       // Traverse the map until the map size is k
       while (freq.size() == K) {
         // Add all valid substrings.
         // If (left, right) contains all K characters, (left, right + 1), (left + right + 2), ...  also contains.
         cnt += len - right;
         // Update character frequency
         freq[alpha[left]]--;
         // Remove the character if its frequency is 0.
         if (freq[alpha[left]] == 0)
            freq.erase(alpha[left]);
         // Move to the next character from left
         left++;
       }
       // Increment the right pointer.
       right++;
     }
     // Increment right by 1
     else {
       right++;
     }
   }
   // Return the value of cnt
   return cnt;
}
int main() {
   string alpha = "abcdda";
   int K = 4;
   cout << "The number of substrings containing all K characters at least once is " << numberOfSubstrings(alpha, K);
   return 0;
}

输出

The number of substrings containing all K characters at least once is 4

时间复杂度 – O(N),对于滑动窗口。

空间复杂度 – O(K),用于在映射中存储频率。

程序员还可以使用数组来存储字符的频率,而不是映射,因为我们可以比映射更快地访问数组中的元素。为了更多练习,程序员尝试解决需要计算仅包含所有K个字符的字符串数量的问题。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程