zoukankan      html  css  js  c++  java
  • 洛谷 P2922 [USACO08DEC]秘密消息Secret Message

    题目描述

    将所有的信息插到Trie树里,对每一条密码,都去已经建好的Trie树中找一次。

    若这条密码的长度比所有 是它的前缀的信息 的长度大,那么每次遇到完整的信息就统计一次答案;

    反之则需统计这条密码是多少条信息的前缀,用一个cnt[i]来记录在Trie树中经过i这个点的信息有多少。

    比较坑的地方是 会有相同的信息,所以还另需记录每条信息的数量。

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int N=5e5+7;
    int n,m,Tnum,ans;
    int trie[N][2],sum[N],num[N],cnt[N];
    char s[N];
    bool flag[N];
    int qread()
    {
        int x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9')ch=getchar();
        while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    void Insert(int a)
    {
        int root=0;
        for(int i=1;i<=a;i++)
        {
            if(!trie[root][num[i]])
                trie[root][num[i]]=++Tnum;
            root=trie[root][num[i]];
            cnt[root]++;
        }
        flag[root]=1;sum[root]++;
    }
    int Query(int a)
    {
        int root=0,res=0;
        for(int i=1;i<=a;i++)
        {
            if(!trie[root][num[i]])return res;
            root=trie[root][num[i]];
            if(flag[root])res+=sum[root];
        }
        res+=cnt[root];
        if(flag[root])res-=sum[root];
        //若到root是一条完整的信息,则需减去这条信息的数量(该条信息被统计了两次) 
        return res;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int a;
        for(int i=1;i<=n;i++)
        {
            a=qread();
            for(int j=1;j<=a;j++)
                num[j]=qread();
            Insert(a);
        }
        for(int i=1;i<=m;i++)
        {
            a=qread();
            for(int j=1;j<=a;j++)
                num[j]=qread();
            printf("%d
    ",Query(a));
        }
        return 0;
    }
  • 相关阅读:
    Android应用开发之避免内存泄露
    史上最经典的数据库面试题之二
    某大型银行深化系统之二十一:Log4j执行性能
    ruby支持批量数组的定义
    为VIM提供python代码提示功能
    使用win7登陆远程机器时自动保存密码
    安装Beanstalk
    在linux下安装或者卸载nginx
    python的数据类型
    使Ruby自动定位查找本地路径
  • 原文地址:https://www.cnblogs.com/LeTri/p/8711397.html
Copyright © 2011-2022 走看看