C++ 将S1中S2的出现次数最大化,分别将N1和N2拼接次数
以下文章讨论了在将字符串S1重复N1次,字符串S2重复N2次后,计算S2在S1中最大出现次数的方法。这是一种有趣的模式搜索问题。在本文中,我们采用了相对直观的解决方案。
问题陈述
任务是确定字符串S2在字符串S1中的最大非重叠出现次数。这些字符串会被多次拼接:S1重复n1次,S2重复n2次。
例子
输入
s1 = “abc”, s2 = “ac”, n1 = 4, n2 = 2
输出
2
解释
在将字符串S1连接四次后,我们得到字符串”abcabcabcabc”。同样,将字符串S2连接两次得到”acac”。通过观察,我们可以确定字符串S2作为一个非重叠子序列出现了两次于字符串S1中。因此,期望的输出是2。
输入
s1 = “”, s2 = “sfa”, n1 = 7, n2 = 8
输出
0
解释
由于s1是一个空字符串,自我连接n1次后,它仍然为空。因此,在s1中不会出现s2连接n2次的情况。
解决方案
该问题的一个可能解决方案是,我们首先分别将字符串s1和s2连接n1和n2次。这样可以确保字符串足够长以相互找到。然后,我们遍历s1中的字符,并检查它们是否等于相应的s2中的字符。如果它们相等,我们继续下一个字符。如果达到s2的长度,我们增加出现的次数。最后,我们返回出现的次数。下面提供的伪代码和C++程序实现了这个方法。
伪代码
- 声明变量
string s1 – 要搜索的字符串
int n1 – s1连接的次数
string s2 – 要搜索的字符串
int n2 – s2连接的次数
- 重复n1次
使用temp连接s1
- 重复n2次
使用temp连接s2
- 遍历s1中的字符
遍历s2中的字符
if current character of string s1 is identical to the current character of string s2,
Increment j and i
Else,
Increment i
If j reaches the length of s2,
Increment the count of occurrences
- 返回出现次数的计数
示例:C++程序
函数countOccurrence()计算s2在s1中出现的次数。n1和n2是s1和s2连接的次数。函数首先将s1与自身连接n1次,将s2与自身连接n2次。然后,它同时迭代s1和s2,检查是否匹配。如果找到匹配,函数增加出现计数器的值。函数返回计数器的最终值。还有一种情况是s2为空字符串。程序返回1,因为空字符串作为子序列出现一次。
示例
#include <iostream>
#include <map>
#include <string>
using namespace std;
// The purpose of this function is to determine the count of occurrences of string s2 within string s1.
// The variables n1 and n2 represent the number of times s1 and s2 are concatenated, respectively.
int countOccurrence(string s1, int n1, string s2, int n2){
string temp = s1;
while (n1 > 1){
s1 += temp;
n1--;
}
temp = s2;
while (n2 > 1){
s2 += temp;
n2--;
}
int i = 0, j = 0, count = 0;
while (i < s1.length()){
j = 0;
while (j < s2.length() && i < s1.length()){
// In the event that the current character of s1 matches the current character of s2,
// increase both j and i by one.
if (s1[i] == s2[j]){
j++;
i++;
}
// Else move on to the next character in 's1'
else{
i++;
}
// If `j` reaches the length of `s2`, increment the count of occurrences.
if (j == s2.length()){
count++;
}
}
}
// Return the count of occurrences.
return count;
}
int main(){
string s1 = "abac";
int n1 = 5;
cout << "s1: " << s1 << " and n1: " << n1 <<endl;
string s2 = "a";
int n2 = 4;
cout << "s2: " << s2 << " and n2: " << n2 << endl;
if (s2.length() == 0){
cout << 1 << endl;
return 0;
}
cout << "count of occurrences of string s2 within string s1: "<< (countOccurrence(s1, n1, s2, n2));
return 0;
}
输出
s1: abac and n1: 5
s2: a and n2: 4
count of occurrences of string s2 within string s1: 2
时间和空间复杂度分析
时间复杂度 :O(NM)
N和M分别是将字符串s1和s2重复连接n1和n2次后的长度。
空间复杂度 :O(N)
在连接字符串时使用了一个临时变量来存储字符串,临时字符串temp的长度为max(length(s1), length(s2))。
结论
本文提出了一种方法来最大化将字符串s2作为s1的子序列出现的次数。这是通过将s1和s2分别连接n1和n2次来实现的。我们通过适当的示例讨论了问题陈述。所提供的解决方案的时间复杂度为O(NM),且相当直观。可以使用Boyer Moore算法的变体更高效地解决这个问题,Boyer Moore算法是一种模式搜索算法。