题目描述
AC鸭收到了一串很长的暗号 s,AK鸭告诉他真正有用的暗号片段是字符串 t。
现在 AC鸭想知道,字符串 t 在字符串 s中一共出现了多少次。
注意:出现位置可以重叠。
例如 aaaaa 中,aaa 出现了 3 次。
输入格式
第一行一个字符串 s,表示完整暗号。
第二行一个字符串 t,表示要寻找的暗号片段。
字符串只包含小写英文字母。
输出格式
输出一个整数,表示 t 在 s 中出现的次数。
样例
输入数据 1
aaaaa
aaa
输出数据 1
3
数据规模
| 子任务 | 占比 | 特殊性质 |
|---|---|---|
| 1 | 20% | ∣t∣=1 |
| 2 | 30% | ∣s∣,∣t∣≤5000 |
| 3 | 50% | 无特殊性质 |
对于全部数据,保证:
1≤∣s∣≤1000000,1≤∣t∣≤100000
正解
问题分析
给定两个字符串 s 和 t,需要在 s 中统计 t 出现的次数(允许重叠)。例如,s = "aaaaa",t = "aaa",输出应为 3(分别在位置 0, 1, 2 匹配)。
方法思路
- 暴力匹配:直接遍历
s的每个位置,检查是否能匹配t。时间复杂度为O(|s| * |t|),在|s|和|t|较大时会超时。 - KMP算法:利用KMP算法中的部分匹配表(前缀函数)来优化匹配过程,将时间复杂度降低到
O(|s| + |t|),适用于大规模数据。
解决代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> computeLPS(const string &pattern) {
int m = pattern.size();
vector<int> lps(m, 0);
int len = 0;
int i = 1;
while (i < m) {
if (pattern[i] == pattern[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
int countOccurrences(const string &text, const string &pattern) {
int n = text.size();
int m = pattern.size();
if (m == 0 || n < m) return 0;
vector<int> lps = computeLPS(pattern);
int i = 0; // index for text
int j = 0; // index for pattern
int count = 0;
while (i < n) {
if (text[i] == pattern[j]) {
i++;
j++;
if (j == m) {
count++;
j = lps[j - 1];
}
} else {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return count;
}
int main() {
string s, t;
cin >> s >> t;
cout << countOccurrences(s, t) << endl;
return 0;
}
代码解释
- computeLPS函数:计算模式串
pattern的最长前缀后缀(LPS)数组。LPS数组用于在KMP算法中跳过不必要的字符比较。 - countOccurrences函数:使用KMP算法统计模式串
pattern在文本text中的出现次数。通过维护两个指针i(文本指针)和j(模式指针),利用LPS数组高效匹配。 - 主函数:读取输入字符串
s和t,调用countOccurrences并输出结果。
这种方法高效且适用于大规模数据,确保在最优时间内解决问题。
问题分析
给定两个字符串 s 和 t,需要在 s 中统计 t 出现的次数(允许重叠)。例如,s = "aaaaa",t = "aaa",输出应为 3(分别在位置 0, 1, 2 匹配)。
方法思路
- 暴力匹配:直接遍历
s的每个位置,检查是否能匹配t。时间复杂度为O(|s| * |t|),在|s|和|t|较大时会超时。 - KMP算法:利用KMP算法中的部分匹配表(前缀函数)来优化匹配过程,将时间复杂度降低到
O(|s| + |t|),适用于大规模数据。
解决代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> computeLPS(const string &pattern) {
int m = pattern.size();
vector<int> lps(m, 0);
int len = 0;
int i = 1;
while (i < m) {
if (pattern[i] == pattern[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
int countOccurrences(const string &text, const string &pattern) {
int n = text.size();
int m = pattern.size();
if (m == 0 || n < m) return 0;
vector<int> lps = computeLPS(pattern);
int i = 0; // index for text
int j = 0; // index for pattern
int count = 0;
while (i < n) {
if (text[i] == pattern[j]) {
i++;
j++;
if (j == m) {
count++;
j = lps[j - 1];
}
} else {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return count;
}
int main() {
string s, t;
cin >> s >> t;
cout << countOccurrences(s, t) << endl;
return 0;
}
代码解释
- computeLPS函数:计算模式串
pattern的最长前缀后缀(LPS)数组。LPS数组用于在KMP算法中跳过不必要的字符比较。 - countOccurrences函数:使用KMP算法统计模式串
pattern在文本text中的出现次数。通过维护两个指针i(文本指针)和j(模式指针),利用LPS数组高效匹配。 - 主函数:读取输入字符串
s和t,调用countOccurrences并输出结果。
这种方法高效且适用于大规模数据,确保在最优时间内解决问题。

545

被折叠的 条评论
为什么被折叠?



