>Link
luogu P3879
ybtoj阅读理解
>Description
英语老师留了 N 篇阅读理解作业,但是每篇英文短文都有很多生词需要查字典,为了节约时间,现在要做个统计,算一算某些生词都在哪几篇短文中出现过。
1 ≤ M ≤ 1 0 4 , 1 ≤ N ≤ 1 0 3 1≤M≤10^4,1≤N≤10^3 1≤M≤104,1≤N≤103
>解题思路
先全部输入完
然后对每篇短文建一棵trie,建完第 i 棵trie以后,对m个单词进行匹配,然后累计答案
(这样可以省空间)
时间复杂度 O ( n m ) O(nm) O(nm)
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1010
#define M 10010
#define S 5010
using namespace std;
int n, m, tot, t[S][30], now, ans[M][N], cnt[M];
int sum[N], len[N][N], lena[M];
string s[N][N], a[M];
bool mark[S];
int main()
{
scanf ("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf ("%d", &sum[i]);
for (int j = 1; j <= sum[i]; j++)
{
cin >> s[i][j];
len[i][j] = s[i][j].size();
s[i][j] = " " + s[i][j];
}
}
scanf ("%d", &m);
for (int i = 1; i <= m; i++)
{
cin >> a[i];
lena[i] = a[i].size();
a[i] = " " + a[i];
}
for (int i = 1; i <= n; i++)
{
memset (t, 0, sizeof (t));
memset (mark, 0, sizeof (mark));
tot = 0;
for (int j = 1; j <= sum[i]; j++)
{
now = 0;
for (int k = 1; k <= len[i][j]; k++)
{
int x = s[i][j][k] - 'a' + 1;
if (!t[now][x]) t[now][x] = ++tot;
now = t[now][x];
}
mark[now] = 1;
}
for (int j = 1; j <= m; j++)
{
now = 0;
for (int k = 1; k <= lena[j]; k++)
{
int x = a[j][k] - 'a' + 1;
now = t[now][x];
if (!now) break;
}
if (mark[now]) ans[j][++cnt[j]] = i;
}
}
for (int i = 1; i <= m; i++)
{
if (!cnt[i])
{
printf ("\n");
continue;
}
for (int j = 1; j < cnt[i]; j++)
printf ("%d ", ans[i][j]);
printf ("%d\n", ans[i][cnt[i]]);
}
return 0;
}