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$的板子題嗎,有什麼可考慮的)

好吧,代碼實現細節及一些注意事項,見代碼了

ios

#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;
}
相關文章
相關標籤/搜索