L 语言:很好的一道状压 dp 题。

思路

看到这题,首先可以想到一个很暴力的 dp,设 \(dp_i\) 表示考虑到第 \(i\) 位能否被理解,暴力匹配字符串转移即可。

第一个优化也很显然,暴力匹配字符串换成 AC 自动机即可。

但是时间复杂度变成了 \(O(m|T||S|)\) 的,显然会被卡。

状压与位运算优化

观察到 \(|S|=20\),所以我们最多只能往前转移 \(20\) 位,这就启发我们用一个 int 存下 dp 状态,用位运算优化转移。这个技巧通常用于可行性 dp 也就是只有 \(0/1\) 状态的 dp 里。

同时我们也需要在 fail 树上预处理出某个节点能接受转移的长度,然后每次和当前 dp 状态与运算一下就好了。

时间复杂度 \(O(m|T|)\)。

坑点

dp 状态取模的时候要取 \(2_i\),如果任取一个数那么会导致 dp 完全乱掉。反例也很好举,例如 \(114514 \bmod 2^{10} \ne 114514 \bmod 1000\)。

同时字典树 insert 要用 insert(s) 而不是 insert(s+1),我已经错了两遍以上了。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
const int mod=2097152;
int n,m,ch[1005][30],idx=0,tot[1005],ne[1005],dp=0,ans=0;
vector<int>g[1005];
char s[1005],t[4000005];
void insert(char *s)
{
int p=0; for(int i=1;s[i];i++)
{
int c=s[i]-'a';
if(ch[p][c]==0)ch[p][c]=++idx;
p=ch[p][c];
}
tot[p]=(tot[p]|(1<<(strlen(s+1))));
}
void build()
{
queue<int>q;
for(int i=0;i<26;i++)
{
if(ch[0][i])q.push(ch[0][i]);
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<26;i++)
{
int v=ch[u][i];
if(v)ne[v]=ch[ne[u]][i],q.push(v);
else ch[u][i]=ch[ne[u]][i];
}
}
}
void dfs1(int u)
{
for(auto v:g[u])
{
tot[v]=(tot[v]|tot[u]);
dfs1(v);
}
}
void init()
{
for(int i=1;i<=idx;i++)g[ne[i]].push_back(i);
dfs1(0);
}
void solve()
{
cin>>t+1;
int len=strlen(t+1),p=0;
dp=1;
ans=0;
for(int i=1;i<=len;i++)
{
int c=t[i]-'a';
p=ch[p][c];
int now=tot[p];
dp<<=1;
dp%=mod;
int hv=(dp&now);
if(hv)dp|=1,ans=i;
if(dp==0)break;
}
cout<<ans<<'\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>s+1;
insert(s);
}
build();
init();
while(m--)solve();
return 0;
}

Luogu P2292 HNOI2004 L 语言 题解 [ 紫 ] [ AC 自动机 ] [ 状压 dp ]的更多相关文章

  1. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  2. Luogu P2292 [HNOI2004]L语言(Trie+dp)

    P2292 [HNOI2004]L语言 题面 题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章 \(T\) 是由若干小写字母构成. ...

  3. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

  4. BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】

    题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...

  5. zoj3545Rescue the Rabbit (AC自动机+状压dp+滚动数组)

    Time Limit: 10 Seconds      Memory Limit: 65536 KB Dr. X is a biologist, who likes rabbits very much ...

  6. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

  7. hdu2825 Wireless Password(AC自动机+状压dp)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  8. 【Luogu】P2292 [HNOI2004]L语言 题解

    前置芝士:\(Trie\)字典树 这道题,说是AC自动机,实际上一个\(Trie+\)队列轻松搞定. 首先,我们对所有单词建一棵\(Trie\). 然后,定义一个空队列\(Q\),初始时把\(-1\) ...

  9. Luogu P2292 [HNOI2004]L语言

    题目链接 \(Click\) \(Here\) 好久没写\(DP\)了真是水平下降不少,一眼把这个题搞成贪心了,然后一发交上只有\(37\)分\(QwQ\) 这个题好像还可以\(AC\)自动机胡搞?不 ...

  10. HDU 2825 Wireless Password(AC自动机 + 状压DP)题解

    题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...

随机推荐

  1. Dockerfile&Docker-Compose之基础

    使用了很久的docker,之前却从来没有总结过, 于是开此篇来记录平常使用Dockerfile和docker-compose.yaml的点滴, 先从基础命令开始哦 [Dockerfile] Docke ...

  2. VLM-OCR-Demo:一个使用VLM用于OCR任务的示例

    前言 上一篇文章TesseractOCR-GUI:基于WPF/C#构建TesseractOCR简单易用的用户界面中我们构建了一个方便使用TesseractOCR的用户界面,今天构建一个类似的界面,使用 ...

  3. winform窗体无边框拖动

    1:引用命名空间 using System.Runtime.InteropServices; 2:想要拖动窗体的控件绑定MouseDown事件 点击查看代码 //窗体移动 [DllImport(&qu ...

  4. 将.nuget文件夹从C盘移到其它盘,再也不用担心的C盘爆红了

    将.nuget文件夹从C盘移到其它盘,再也不用担心的C盘爆红了 命令 查看缓存文件夹的具体路径 dotnet nuget locals all --list 第一步 在文件资源管理器输入%AppDat ...

  5. 树莓派4B 多屏 QT程序窗口全屏 QScreen 只能获取1个屏幕

    直接运行程序时,窗口全屏, 并且QScreen 只能获取1个屏幕,这是由于QT默认使用了EGLFS.(坑了一下午) 所以必须采用命令方式打开程序. ./程序名称 -platform xcb

  6. 让低版本gitlab焕新 —— 如何在低版本gitlab上实现高版本API功能

    前言:本文主要记录了基于低版本gitlab(v3 api)实现in-line comment功能的过程中踩过的坑及相应的解决方案,理论上其他低版本gitlab不具备的API都可以参照此类方法进行实现( ...

  7. GraphQL Part VI: 使用 Postgres 和 EF Core 持久化数据

    这次我们关注持久化数据而不是 GraphQL 方面.我们将使用 Postgres 数据库作为后端存储,您可能问:为什么要使用 Postgres?因为大家都熟悉 SQL Server,我们尝试一下新东西 ...

  8. macOS 中有什么好用的虚拟机软件?

    macOS 中有什么好用的虚拟机软件? https://www.zhihu.com/question/66366176/answer/268256386 问题:1.macOS是否有专门的虚拟机软件?或 ...

  9. 解决phpmyadmin导入MYSQL数据库限制大小为50M的问题

    有时候想导入的数据库太大.但是遭到的限制 解决phpmyadmin导入MYSQL数据库限制大小为50M的问题 转载于:https://www.cnblogs.com/wesky/p/10609340. ...

  10. Qt编写视频监控系统78-视频推流到流媒体服务器

    一.前言 视频推流作为独立的模块,目前并没有集成到视频监控系统中,目前是可以搭配监控系统一起使用,一般是将添加好的摄像头通道视频流地址打开后,读取视频流重新推到流媒体服务器,然后第三方可以从流媒体服务 ...