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;
    }
  • 相关阅读:
    hibernate理解
    struts理解
    网上书城项目
    编码过程中遇到的问题
    JS回调函数
    requirejs 一个拆分js项目的类库
    jq插件开发总结
    转载-- 魔兽哈希算法封装和测试
    转载--C# PLINQ 内存列表查询优化历程
    Oracle删除死锁进程的方法
  • 原文地址:https://www.cnblogs.com/LeTri/p/8711397.html
Copyright © 2011-2022 走看看