阅读理解【Trie】

>Link

luogu P3879

ybtoj阅读理解


>Description

英语老师留了 N 篇阅读理解作业,但是每篇英文短文都有很多生词需要查字典,为了节约时间,现在要做个统计,算一算某些生词都在哪几篇短文中出现过。

1 ≤ M ≤ 1 0 4 , 1 ≤ N ≤ 1 0 3 1≤M≤10^4,1≤N≤10^3 1M1041N103


>解题思路

先全部输入完
然后对每篇短文建一棵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;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/120948588