题目地址:
https://www.acwing.com/problem/content/description/4401/
给定 n n n个字符串 f 1 , f 2 , … , f n f_1,f_2,…,f_n f1,f2,…,fn。这些字符串两两不同。下面给定 q q q个询问。其中,第 i i i次询问给定一个字符串 s i s_i si,你的任务是:计算 f 1 ∼ f n f_1∼f_n f1∼fn这 n n n个字符串中,包含 s i s_i si作为子串的字符串的数量。从 f 1 ∼ f n f_1∼f_n f1∼fn这 n n n个字符串中,任选一个包含 s i s_i si作为子串的字符串输出。
输入格式:
第一行包含整数
n
n
n。
接下来
n
n
n行,其中第
i
i
i行包含字符串
f
i
f_i
fi。
再一行包含整数
q
q
q。
接下来
q
q
q行,其中第
i
i
i行包含字符串
s
i
s_i
si。
所有
f
i
f_i
fi和
s
i
s_i
si都只包含小写字母、数字以及.
。
输出格式:
共
q
q
q行,其中第
i
i
i行输出第
i
i
i个询问的答案。
首先输出
f
1
∼
f
n
f_1∼f_n
f1∼fn这
n
n
n个字符串中包含
s
i
s_i
si作为子串的字符串的数量。然后从
f
1
∼
f
n
f_1∼f_n
f1∼fn这
n
n
n个字符串中任选一个包含
s
i
s_i
si作为子串的字符串输出。
如果这样的字符串不唯一,则输出任意合理字符串均可,如果这样的字符串不存在,则输出-
。
数据范围:
前三个测试点满足
1
≤
n
,
q
≤
20
1≤n,q≤20
1≤n,q≤20。
所有测试点满足
1
≤
n
≤
10000
1≤n≤10000
1≤n≤10000,
1
≤
q
≤
50000
1≤q≤50000
1≤q≤50000,
1
≤
∣
f
i
∣
,
∣
s
i
∣
≤
8
1≤|f_i|,|s_i|≤8
1≤∣fi∣,∣si∣≤8。
观察到每个字符串都很短,可以直接用两个哈希表,一个存每个子串出现在多少个原串里,另一个存每个子串存在于哪个原串里。代码如下:
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
unordered_map<string, int> mp, mp1;
unordered_set<string> st;
vector<string> vs;
int n, q;
int main() {
scanf("%d", &n);
string s;
for (int i = 0; i < n; i++) {
cin >> s;
vs.push_back(s);
st.clear();
for (int j = 0; j < s.size(); j++)
for (int k = j; k < s.size(); k++) {
auto t = s.substr(j, k - j + 1);
if (!st.count(t)) {
st.insert(t);
mp1[t] = i;
mp[t]++;
}
}
}
scanf("%d", &q);
while (q--) {
cin >> s;
if (!mp[s])
puts("0 -");
else
cout << mp[s] << " " << vs[mp1[s]] << endl;
}
}
预处理时间复杂度 O ( ∑ i l i 3 ) O(\sum_i l_i^3) O(∑ili3),每次查询时间 O ( l s ) O(l_s) O(ls),空间 O ( ∑ i l i ) O(\sum_i l_i) O(∑ili)。