[HNOI2004] L 语言 题解(AC 自动机上 dp)
前言:
原版数据超弱,爆搜就能过(即洛谷里面 80 分的数据),在此不多说,这里讲的是正解。(如果不是正解我还敢写题解吗)
唔······话说洛谷里的题解用的都有状压,蒟蒻表示这题不用状压也能过(欢迎各位大佬 hack 我的做法,把我的做法弄到 TLE)。
正文:
令
但是数据范围不小,暴力枚举前面的那些字母去匹配是会超时的。看到多模式串,我们肯定得想到 AC 自动机喽。
然鹅······
大家可以看到,不动脑子地套上 AC 自动机后虽然比暴力多了 5 分,但还是不能通过全部数据。
我在交这份代码前也意识到了这点,所以又写了些优化,于是就过了。
讲下优化吧:
-
在算
的时候,如果它已经可以为 ,就跳出循环。 -
在算
的时候,如果之前最多能匹配到的那一位离现在差的位数大于模式串长度的最大值,直接输出答案。举个例子,如今在算第 位的答案,但是当前最多只能匹配到第 位,那么就没必要继续算了,答案就取 。因为你至少需要长度为 的模式串才可能让当前长度能匹配,但是找不到这么长的模式串,所以再往后就更不可能了。 -
在跳失配数组的时候,其中很多对答案都没有贡献(即不在叶子结点的),所以我们在求失配数组时,可以再开个数组,把实际该跳到哪里给记录下来,这个做法在 P3796 【模板】AC 自动机(加强版)中有人提及。不过我的代码经过实测,不加该优化也可以 AC,我下面放的代码也是没有这个优化的。当然,加上它应该会更快些。
Code:
#include<bits/stdc++.h>
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define inf 0x7fffffff
#define INF 0x3f
#define v e[i].y
using namespace std;
inline ll read(){
char ch=getchar();ll x=0,w=1;
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();return w==1?x:-x;
}
inline void write(ll x){
if(x<0)x=-x,putchar('-');
if(x<10){putchar(48+x);return;}
write(x/10),putchar((x+10)%10+48);
}
int n=read(),m=read(),q[100005],ans,h,t,maxl;
bool dp[2000005];
char xk[2000005];
struct AC{
int ch[30005][30],Fail[30005],val[30005],num;
void Insert(int L){
int op=0;
for(int i=1,j;i<=L;i++){
j=xk[i]-'a';
op=(ch[op][j]?ch[op][j]:ch[op][j]=++num);
}
val[op]=L,maxl=max(maxl,L);
}
void getfail(){
h=0,t=0;
for(int i=0;i<26;i++)if(ch[0][i])q[++t]=ch[0][i],Fail[ch[0][i]]=0;
while(h<t){
int u=q[++h];
for(int i=0;i<26;i++){
if(ch[u][i])Fail[ch[u][i]]=ch[Fail[u]][i],q[++t]=ch[u][i];
else ch[u][i]=ch[Fail[u]][i];
}
}
}
int solve(int L){
for(int i=1;i<=L;i++)dp[i]=0;
dp[0]=1,ans=0;
int op=0;
for(int i=1,j;i<=L;i++){
if(ans+maxl<i)break;
j=xk[i]-'a',op=ch[op][j];
for(int k=op;k;k=Fail[k]){
dp[i]|=dp[i-val[k]];
if(dp[i])break;
}
if(dp[i])ans=i;
}
return ans;
}
}A;
int main(){
while(n--)scanf("%s",xk+1),A.Insert(strlen(xk+1));
A.getfail();
while(m--)scanf("%s",xk+1),write(A.solve(strlen(xk+1))),putchar(10);
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!