📅  最后修改于: 2023-12-03 15:42:13.974000             🧑  作者: Mango
给定一个字符串 $s$ 和一个数字 $k$,求出 $s$ 中的所有长度为 $k$ 的子串,并且按字典序从小到大输出。
第一行包含一个整数 $T$,表示数据组数。
每组数据包含两行,第一行包含一个字符串 $s$,第二行包含一个整数 $k$。
对于每组数据,按照字典序从小到大输出所有长度为 $k$ 的子串,每个子串占一行。
2
luogu
3
hello
2
g
l
o
ogu
ugu
h
e
l
ll
lo
o
本题可以使用滑动窗口算法来解决。首先移动窗口,直至窗口大小为 $k$,然后输出此时窗口中的子串。然后每次移动窗口时,保留窗口左端点,移动右端点,如此往复。具体实现中,为了保证字典序的正确性,我们可以通过一个优先队列来保存当前窗口中的子串,并定义小于符号,保证待输出的子串始终是当前窗口中的最小值。
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1010;
int n;
int k;
char s[N];
struct SubStr {
int idx;
char s[N];
bool operator< (const SubStr &t) const {
for (int i = 0; i < k; i ++ )
if (s[idx + i] != t.s[t.idx + i])
return s[idx + i] > t.s[t.idx + i];
return false;
}
};
int main() {
int T;
cin >> T;
while (T -- ) {
priority_queue<SubStr> q;
cin >> s + 1 >> k;
n = strlen(s + 1);
for (int i = 1; i <= k; i ++ ) q.push({0, s});
while (!q.empty()) {
auto t = q.top();
q.pop();
cout << string(t.s + t.idx + 1, t.s + t.idx + k + 1) << endl;
if (t.idx + k == n) continue;
t.idx ++ ;
q.push(t);
}
}
return 0;
}
时间复杂度 $O(n\log n)$,其中 $n$ 是字符串长度。