• Luogu P3879 【[TJOI2010]阅读理解】


    前言:

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

    $5e6 imes26 imes4div1024div1024approx496Mb>125Mb$

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

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

    正文:

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

    $10000 imes20 imes26 imes4div1024div1024approx20Mb$

    占空间最多的$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("
    ");
        }
        /*这里的输出,因为一篇文章里可能多次出现同一单词,
        记得去重,一开始我用的unique,再输出vector中的
        所有元素。但是unique去重时其实并没有删除这些元素
        在这里也被坑了,所以改用迭代器*/
        return 0;
    }



  • 相关阅读:
    Win10 UWP Tile Generator
    Win10 BackgroundTask
    UWP Tiles
    UWP Ad
    Win10 build package error collections
    Win10 八步打通 Nuget 发布打包
    Win10 UI入门 pivot multiable DataTemplate
    Win10 UI入门 导航滑动条 求UWP工作
    UWP Control Toolkit Collections 求UWP工作
    Win10 UI入门 SliderRectangle
  • 原文地址:https://www.cnblogs.com/ivanovcraft/p/11342215.html
Copyright © 2020-2023  润新知