Luogu P3879 【[TJOI2010]阅读理解】

前言:

这个题一直有个疑问,最多一千行,每行五千字$1000\times5000=5e6$

$5e6\times26\times4\div1024\div1024\approx496Mb>125Mb$

尽管清楚实际空间需求不能到达$5e6$,如何计算直接对文章建$Trie$事实上所需的最大空间呢,本人对此并不清楚,也希望有大佬能为我解决一下这个问题(至于开$5e6\times26$通过的大佬,我想我这种凡人还达不到这个境界)

那么,就请我们权且认为直接对文章建$Trie$在空间上是不被允许的,至少是不够保险的

正文:

于是提供一种同样是基于$Trie$的方法——对询问建$Trie$

$10000\times20\times26\times4\div1024\div1024\approx20Mb$

占空间最多的$Trie$解决了,空间问题就不必担心了

下面我们考虑对询问建$Trie$下这个问题的解决

(这不是$Trie$的板子题吗,有什么可考虑的)

好吧,代码实现细节及一些注意事项,见代码了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=5e6,maxq=2e5+10;
int cnt,a[maxq][26],n,m;
vector<string>v[1010];
vector<int>ans[10010],val[maxq];
string tmp;
int idx(char c)
{
    return c-'a';
}
void insert(int x)
{
    cin>>tmp;
    int len=tmp.length(),now=0;
    for(int i=0;i<len;i++)
    {
        int c=idx(tmp[i]);
        now=a[now][c]?a[now][c]:a[now][c]=++cnt;
    }
    val[now].push_back(x);
    /*因为可能有相同的查询,这里的简单地用一个
    整形标记就不太合适了,我选择了用vector记录
    这个节点作为所有询问的标记*/
}
void check(int x,int y)
{
    int len=v[x][y].length(),now=0;
    for(int i=0;i<len;i++)
    {
        int c=idx(v[x][y][i]);
        if(!a[now][c])
            return;
            //这个单词一定没有被查询过,直接退回
        now=a[now][c];
    }
    for(int i=0;i<val[now].size();i++)
        ans[val[now][i]].push_back(x);
        //同理在所有询问中保存这个单词曾经出现的文章
}
int main()
{
    scanf("%d",&n);
    for(int i=1,num;i<=n;i++)
    {
        scanf("%d",&num);
        for(int j=1;j<=num;j++)
        {
            cin>>tmp;
            v[i].push_back(tmp);
            //采用了vector来存储原文
        }
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        insert(i);
    for(int i=1;i<=n;i++)
        for(int j=0;j<v[i].size();j++)
            check(i,j);
    for(int i=1;i<=m;i++)
    {
        vector<int>::iterator pos=unique(ans[i].begin(),ans[i].end());
        for(vector<int>::iterator it=ans[i].begin();it!=pos;it++)
            printf("%d ",*it);
        printf("\n");
    }
    /*这里的输出,因为一篇文章里可能多次出现同一单词,
    记得去重,一开始我用的unique,再输出vector中的
    所有元素。但是unique去重时其实并没有删除这些元素
    在这里也被坑了,所以改用迭代器*/
    return 0;
}

 



posted @ 2019-08-12 20:00  Ivanovcraft  阅读(148)  评论(0编辑  收藏  举报