【Trie】洛谷P2922 秘密信息

链接

https://www.luogu.org/problem/show?pid=2922

大意

给定 n 个已加密元素, m 个钥匙
(感性理解一下。。。)

问每把钥匙串与加密串的最长前缀

思路

T r i e
s u m 表示中间字符的出现次数, e n d 表示当前串的出现次数
做一遍 T r i e 即可

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int trie[500001][2],tot,n,ans,end[500001],cnt[500001],sum[500001],m;
bool a[500001];
inline void insert(register bool a[],register int len)
{
    int p=0;
    for(register int k=1;k<=len;k++)
    {
        if(!trie[p][a[k]]) trie[p][a[k]]=++tot;
        p=trie[p][a[k]];
        sum[p]++;//字符出现次数
    }
    end[p]++;//该串出现次数
    return;
}
inline void search(register bool a[],register int len)
{
    int p=0,ans=0;
    for(register int k=1;k<=len;k++)
    {
        if(!trie[p][a[k]])
        {
            printf("%d\n",ans);//无法拓展直接输出
            return;
        }
        p=trie[p][a[k]];
        ans+=end[p];//加上子串
    }
    printf("%d\n",ans-end[p]+sum[p]);//能完全找到,减去之前所有的end加上sum
    return;
}
signed main()
{
    scanf("%d%d",&n,&m);
    for(register int i=1,t;i<=n;i++)
    {
        scanf("%d",&t);
        for(register int j=1;j<=t;j++) scanf("%d",a+j);
        insert(a,t);
    }
    for(register int i=1,t;i<=m;i++)
    {
        scanf("%d",&t);
        for(register int j=1;j<=t;j++) scanf("%d",a+j);
        search(a,t);
    }
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/81778981