Clannad【2018四川省赛】【AC自动机 + DP】

2023-10-29

题目链接(第十届四川省赛C题)


  挺好的一道题,就是要做一个last优化,每次的last要返回到之前的有值节点,也就是单词的尾的对应节点,然后就不会超时了…… 呜呜呜,之前一直超时,以为是初始化的memset()问题,以前被卡过memset(),然后发现其实要是有多个相同的节点,岂不是会反复无常的跑无用的fail指针,于是就用了last优化掉了,过了。过咯!

  对了,用DP推状态,这个比划一下,挺简单的,就是推对应后缀的去掉后缀的字符串的状态的\sum求和。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e5 + 7;
const int mod = 1e9 + 7;
int N, M;
char virus[maxN], sss[maxN];
ll dp[maxN];
struct node
{
    node *next[26];
    node *fail, *las;   //las用来寻找上一个为sum==1的点用以优化路径
    int sum, len;
    node()
    {
        for(int i=0; i<26; i++) next[i] = NULL;
        fail = NULL;    las = NULL;
        sum = len = 0;
    }
};
node *root;
void update(char *s)
{
    node *temp = root;
    int len = (int)strlen(s);
    for(int i=0; i<len; i++)
    {
        int x = s[i] - 'a';
        if(temp->next[x] == NULL) temp->next[x] = new node();
        temp = temp->next[x];
    }
    temp->sum = 1;
    temp->len = len;
}
void build_fail()
{
    queue<node *> Q;
    Q.push(root);
    node *temp, *p;
    while(!Q.empty())
    {
        temp = Q.front();   Q.pop();
        for(int i=0; i<26; i++)
        {
            if(temp->next[i])
            {
                if(temp == root)
                {
                    temp->next[i]->fail = root;
                    temp->next[i]->las = root;
                }
                else
                {
                    p = temp->fail;
                    while(p)
                    {
                        if(p->next[i])
                        {
                            temp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(!p) temp->next[i]->fail = root;
                    else
                    {
                        if(p->next[i]->sum > 0) temp->next[i]->las = p->next[i];
                        else temp->next[i]->las = p->next[i]->las;
                    }
                }
                Q.push(temp->next[i]);
            }
        }
    }
}
void AC_auto()
{
    node *p = root;
    for(int i=1; i<=N; i++)
    {
        int x = virus[i] - 'a';
        while(p != root && !p->next[x]) p = p->fail;
        p = p->next[x];
        if(!p) p = root;
        node *temp = p;
        while(temp && temp != root)
        {
            if(temp->sum > 0)
            {
                dp[i] += dp[i - temp->len];
                if(dp[i] >= mod) dp[i] -= mod;
            }
            temp = temp->las;
        }
    }
}
inline void init()
{
    for(int i=1; i<=N; i++) dp[i] = 0;
    dp[0] = 1;
    root = (node *)malloc(sizeof(node));
    for(int i=0; i<26; i++) root->next[i] = NULL;
    root->fail = NULL;  root->las = NULL;
    root->sum = 0;
}
int main()
{
    int T;  scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &N, &M);
        init();
        scanf("%s", virus + 1);
        for(int i=1; i<=M; i++)
        {
            scanf("%s", sss);
            update(sss);
        }
        build_fail();
        AC_auto();
        for(int i=1; i<=N; i++) printf("%lld%c", dp[i], i==N?'\n':' ');
    }
    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Clannad【2018四川省赛】【AC自动机 + DP】 的相关文章

  • 到底还有没有月薪3万以下的程序员?程序员工资真的这么高?

    最近被 月薪5万过得像5千 的 西二旗生活指北 刷屏 文章直指 海淀西北角的群众们不仅能把月入5万活得像5千 他们还能把月入10万 20万 50万也活得像月入5千 我关注的点不在于 活得像月入5千 这对我来说一点难度都没有 我能活得像月入5
  • 万向节死锁产生的原因

    万向节死锁产生的根本原因是 旋转矩阵是依次进行的 假设先围绕x轴旋转 再围绕y轴旋转 最后围绕z轴旋转 这就导致物体其实是围绕自己的X轴旋转 而不是世界坐标的X轴旋转 表现就是 在一个欧拉角 x y z 下 改变x的值 物体会围绕物体自己的

随机推荐

  • Kendo UI开发教程(11): Kendo MVVM (二) ObservableObject 对象

    概述 Kendo MVVM框架关键的一个部分为ViewModel 它主要是通过kendo data ObserableObject来提供支持的 它可以监控改变 UI变化或是值的变化 并通知关心该变化的组件 本篇以下ViewModel 和 O
  • sqli-labs靶场第一关

    开始第一关之前 我们先在火狐上下载一个插件hackbar 点火狐右上角的菜单 找到扩展和主题 在扩展中搜索hackbar 点击下载第一个hackbar插件 下载完成之后 我们开始sql靶场第一关的解析过程 下载hackbar主要是为了后续操
  • H.264 视频的 RTP 载荷格式

    本文是 IETF 的规范 RFC 6184 的一部分的翻译 该规范 地址 翻译这份文档 主要是为了编写一段用 RTP 传输 H 264 流的代码 本想在网上找一些文章完成任务了事的 但由于个人之前音视频编解码相关的知识比较匮乏 网上找的文章
  • 防网关病毒的知识

    1 什么是恶意软件 恶意软件官方的一个定义 恶意软件 Malware 从 恶意 malicious 和 软件 software 这两个词合并而来 是一个通用术语 可以指代病毒 蠕虫 特洛伊木马 勒索软件 间谍软件 广告软件和其他类型的有害软
  • 怎么引css样式,jsp怎么引入css样式?

    JSP页面引入CSS样式有三种方法 且其优先级不同 具体如下 外部样式 内嵌样式 行内样式 优先级依次增高 下面给大家具体介绍一下 1 外部样式 jsp可以在link标签中使用href属性引入css文件路径 首先把写好的css样式表内容存为
  • Linux里的2>&1究竟是什么

    我们在Linux下经常会碰到nohup command gt dev null 2 gt 1 这样形式的命令 首先我们把这条命令大概分解下首先就是一个nohup表示当前用户和系统的回话下的进城忽略响应HUP消息 是把该命令以后台的job的形
  • 德勤与Attest合作,开发政府级区块链身份管理系统

    11月5日报道 四大会计师事务所之一的德勤 Deloitte 与身份管理公司Attest合作 开发了基于区块链的政府级数字身份系统 区块链开发 位于芝加哥的身份管理公司Attest提供了一个共享的身份平台 客户可以在这里进行交易 政府客户可
  • QT 线程常见需要注意的问题

    C C 程序都是从main 函数开始执行的 main 函数其实就是主进程的入口 main 函数退出了 则主进程退出 整个进程也就结束了 而对于使用Qthread创建的进程而言 run 函数则是新线程的入口 run 函数退出 意味着线程的终止
  • react-hooks 在不编写 class 的情况下使用 state 以及其他的 React 特性

    文章目录 hooks 一 hook 1 useState 2 useEffect 3 useLayoutEffect 4 自定义Hook 5 useRef 6 useImperativeHandle 7 useContext 8 useRe
  • led灯条串联图_单片机入门教学-LED驱动电路

    欢迎关注 嵌入式干货铺子 每日更新干货教程 做单片机开发 看不懂电路图是万万不能的 分析电路原理图是一个合格的单片机工程师必须掌握的 后续干货铺子会做一个分析电路图的系列教程 从最基本的电路开始 手把手掌握单片机电路的设计 欢迎大家关注 接
  • Java 基本数据类型(四类八种)

    基本数据类型 四类八种 整数类 byte short int long 浮点类 float double 字符类 char 布尔型 boolean 除此之外即为引用类数据类型 一 整数类 不同类型表示不同长度 1 Byte 使用1个字节存储
  • 共识算法 —— PoA

    定义 PoA的全称是 Proof Of Authority 权威证明 网上有些文章全称写得是 Proof Of Activity 个人感觉明显不对 大家自行鉴别 最早提出人是Ethereum 以太坊前技术专家Gavin Wood 在2017
  • hive小文件过多问题解决方法

    小文件产生原因 hive 中的小文件肯定是向 hive 表中导入数据时产生 所以先看下向 hive 中导入数据的几种方式 直接向表中插入数据 insert into table A values 1 zhangsan 88 2 lisi 6
  • 如此优雅,4款 Python 自动数据分析神器真香啊

    我们做数据分析 在第一次拿到数据集的时候 一般会用统计学或可视化方法来了解原始数据 比如了解列数 行数 取值分布 缺失值 列之间的相关关系等等 这个过程我们叫做 EDA Exploratory Data Analysis 探索性数据分析 用
  • 一文看懂什么是区块链分叉

    一些链上资产采用的工作量证明机制 就是让矿工互相竞争求解一个数学题 谁先解出来了 他就大喊一声 我的工作量证明成功了 你们快来看 全体矿工就都过来把那一页目抄写一份 贴在自己账本的最后面 然后又开始新的记账过程 在这个过程中 经常会出现这样
  • 通俗易懂----C语言时间日期与时间戳互相转化

    前言 如果你也对时间转化的高效代码而苦恼 不妨看看以下内容 一定会给你带来良好的体验和启迪 1 时间戳含义 1 1时间戳是衡量时间的一种标准 用来特定电子数据提供一个绑定时间戳 从而有效地证明该电子数据的产生时间及未被修改 常用于保 防伪等
  • 前端小作业~基础知识点串接

    包子们 这次网页虽然不难 但是扣细节的地方多啊 都是最近学的零零散散的知识的拼接与整合 也是尽力而为了 搞了将近四个小时
  • R语言常用快捷键1

    快捷键 1赋值符号 lt alt 2管道符 gt Ctrl Shift M 3注释 Ctrl Shift C 4默认颜色 5折叠所有代码 alt o 6展开所有代码 shift alt o 7添加代码块 Ctrl alt i 1赋值符号 l
  • [从零学习汇编语言] - 转移指令进阶

    文章目录 前言 回顾 1 转移指令原理 2 已接触过的操作符 3 寄存器回顾 通用数据处理寄存器 指针寄存器 变址寄存器 段地址寄存器 其他寄存器 一 ret及retf 1 1 ret指令 1 2 retf指令 1 3 小练习 二 Call
  • Clannad【2018四川省赛】【AC自动机 + DP】

    题目链接 第十届四川省赛C题 挺好的一道题 就是要做一个last优化 每次的last要返回到之前的有值节点 也就是单词的尾的对应节点 然后就不会超时了 呜呜呜 之前一直超时 以为是初始化的memset 问题 以前被卡过memset 然后发现