Luogu P2292 HNOI2004 L 语言 题解 [ 紫 ] [ AC 自动机 ] [ 状压 dp ]
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 ]的更多相关文章
- hdu 2825 aC自动机+状压dp
Wireless Password Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- Luogu P2292 [HNOI2004]L语言(Trie+dp)
P2292 [HNOI2004]L语言 题面 题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章 \(T\) 是由若干小写字母构成. ...
- HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解
题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...
- BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】
题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...
- zoj3545Rescue the Rabbit (AC自动机+状压dp+滚动数组)
Time Limit: 10 Seconds Memory Limit: 65536 KB Dr. X is a biologist, who likes rabbits very much ...
- hdu 4057--Rescue the Rabbit(AC自动机+状压DP)
题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...
- hdu2825 Wireless Password(AC自动机+状压dp)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...
- 【Luogu】P2292 [HNOI2004]L语言 题解
前置芝士:\(Trie\)字典树 这道题,说是AC自动机,实际上一个\(Trie+\)队列轻松搞定. 首先,我们对所有单词建一棵\(Trie\). 然后,定义一个空队列\(Q\),初始时把\(-1\) ...
- Luogu P2292 [HNOI2004]L语言
题目链接 \(Click\) \(Here\) 好久没写\(DP\)了真是水平下降不少,一眼把这个题搞成贪心了,然后一发交上只有\(37\)分\(QwQ\) 这个题好像还可以\(AC\)自动机胡搞?不 ...
- HDU 2825 Wireless Password(AC自动机 + 状压DP)题解
题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...
随机推荐
- Dockerfile&Docker-Compose之基础
使用了很久的docker,之前却从来没有总结过, 于是开此篇来记录平常使用Dockerfile和docker-compose.yaml的点滴, 先从基础命令开始哦 [Dockerfile] Docke ...
- VLM-OCR-Demo:一个使用VLM用于OCR任务的示例
前言 上一篇文章TesseractOCR-GUI:基于WPF/C#构建TesseractOCR简单易用的用户界面中我们构建了一个方便使用TesseractOCR的用户界面,今天构建一个类似的界面,使用 ...
- winform窗体无边框拖动
1:引用命名空间 using System.Runtime.InteropServices; 2:想要拖动窗体的控件绑定MouseDown事件 点击查看代码 //窗体移动 [DllImport(&qu ...
- 将.nuget文件夹从C盘移到其它盘,再也不用担心的C盘爆红了
将.nuget文件夹从C盘移到其它盘,再也不用担心的C盘爆红了 命令 查看缓存文件夹的具体路径 dotnet nuget locals all --list 第一步 在文件资源管理器输入%AppDat ...
- 树莓派4B 多屏 QT程序窗口全屏 QScreen 只能获取1个屏幕
直接运行程序时,窗口全屏, 并且QScreen 只能获取1个屏幕,这是由于QT默认使用了EGLFS.(坑了一下午) 所以必须采用命令方式打开程序. ./程序名称 -platform xcb
- 让低版本gitlab焕新 —— 如何在低版本gitlab上实现高版本API功能
前言:本文主要记录了基于低版本gitlab(v3 api)实现in-line comment功能的过程中踩过的坑及相应的解决方案,理论上其他低版本gitlab不具备的API都可以参照此类方法进行实现( ...
- GraphQL Part VI: 使用 Postgres 和 EF Core 持久化数据
这次我们关注持久化数据而不是 GraphQL 方面.我们将使用 Postgres 数据库作为后端存储,您可能问:为什么要使用 Postgres?因为大家都熟悉 SQL Server,我们尝试一下新东西 ...
- macOS 中有什么好用的虚拟机软件?
macOS 中有什么好用的虚拟机软件? https://www.zhihu.com/question/66366176/answer/268256386 问题:1.macOS是否有专门的虚拟机软件?或 ...
- 解决phpmyadmin导入MYSQL数据库限制大小为50M的问题
有时候想导入的数据库太大.但是遭到的限制 解决phpmyadmin导入MYSQL数据库限制大小为50M的问题 转载于:https://www.cnblogs.com/wesky/p/10609340. ...
- Qt编写视频监控系统78-视频推流到流媒体服务器
一.前言 视频推流作为独立的模块,目前并没有集成到视频监控系统中,目前是可以搭配监控系统一起使用,一般是将添加好的摄像头通道视频流地址打开后,读取视频流重新推到流媒体服务器,然后第三方可以从流媒体服务 ...