AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

2922Secret Message G

作者: 作者的头像   cccccccup ,  2025-05-09 21:11:00 · 福建 ,  所有人可见 ,  阅读 2


0


题目

微信截图_20250509210401.png

难点:
对于前缀的计算要理解清楚
比如对于暗号:11,有相同前缀的信息既有1也有110

我的处理

对于一个信息串,每一位上的cnt[]都++
然后在对暗号进行判断时

if(i==len-1) res+=cnt[p];
else res=res+cnt[p]-cnt[son[p][0]]-cnt[son[p]

如果当前字符i不是暗号的最后一个字母,那么当前cnt就要减去两个子串的cnt(才是单独的以字符i为结尾的子串数量)
如果i是暗号的最后一个字符了,那就直接加上cnt[]

微信图片_20250509211152.jpg

题解记录

区分两种记录:
经过该节点的字符串数 和 以该节点为尾巴的字符串数

我的题解相当于没有只记录了“经过该节点的字符串数”,然后通过这个算出了“以该节点为尾巴的字符串数”

#include <bits/stdc++.h>
using namespace std;

const int N=5e5+7;
const int M=1e+7;
int son[N][2];
int cnt[N];
int idx;
int m,n;
int mes[M],len;

void insert(int mes[],int len)
{
    //注意mes的每个位上对应的数字的cnt都要++
    int p=0;
    for(int i=0;i<len;i++){
        int u=mes[i];
        if(son[p][u]==0) son[p][u]=++idx;
        p=son[p][u];
        cnt[p]++;
    }
}

int query(int mes[],int len)
{
    int p=0;
    int res=0;
    for(int i=0;i<len;i++){
        int u=mes[i];
        if(son[p][u]==0){
            break;
        }
        p=son[p][u];
        if(i==len-1) res+=cnt[p];
        else res=res+cnt[p]-cnt[son[p][0]]-cnt[son[p][1]];
    }
    return res;
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=0;i<m;i++){
        //第i条信息
        scanf("%d",&len);
        for(int i=0;i<len;i++) scanf("%d",&mes[i]);
        insert(mes,len);
    }
    for(int i=0;i<n;i++){
        //第i次询问
        scanf("%d",&len);
        for(int i=0;i<len;i++) scanf("%d",&mes[i]);
        printf("%d\n",query(mes,len));
    }
    return 0;
}

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息