当前位置:网站首页>P6698-[BalticOI 2020 Day2]病毒【AC自动机,dp,SPFA】
P6698-[BalticOI 2020 Day2]病毒【AC自动机,dp,SPFA】
2022-06-24 07:49:00 【QuantAsk】
正题
题目链接:https://www.luogu.com.cn/problem/P6698
题目大意
有一个包含 0 ∼ G − 1 0\sim G-1 0∼G−1的字符集,其中有 n n n种变换,能够将一个字符 a i ( a i > 1 ) a_i(a_i>1) ai(ai>1)变为一串字符 b i b_i bi,当一个字符串中只剩下 0 0 0和 1 1 1时变换就结束了。
然后给出 m m m个匹配串 c i c_i ci。现在对于每个字符 i ∈ [ 2 , G − 1 ] i\in[2,G-1] i∈[2,G−1],是否字符 i i i无论变化结束时都含有至少一个匹配串,如果不是,求一个最短的不包含任何匹配串的最终串长度。
保证每个在 [ 2 , G − 1 ] [2,G-1] [2,G−1]的字符都能进行变化,匹配串中只包含 0 / 1 0/1 0/1。
∑ t i ≤ 50 , ∑ ∣ b i ∣ ≤ 100 , n ≤ 100 , 2 < G ≤ n + 2 \sum t_i\leq 50,\sum |b_i|\leq 100,n\leq 100,2<G\leq n+2 ∑ti≤50,∑∣bi∣≤100,n≤100,2<G≤n+2
解题思路
有匹配的问题,我们先拿所有的 c i c_i ci出来建一棵AC自动机,然后考虑怎么计算每个字符能从哪个状态跳到哪个状态。
注意我们在AC自动机上走状态时不能走到包含匹配串的状态,这样我们可以将无论如何都包含匹配串视为最短不包含匹配串的长度无穷大。
那么我们考虑dp这个最短的长度,设 f i , s , t f_{i,s,t} fi,s,t表示字符 i i i经过变换后,能从状态 s s s走到状态 t t t的最短长度。
转移时我们考虑枚举一个变换 i i i,再枚举一个起点 s s s,然后设 g j , x g_{j,x} gj,x表示现在走到 b i , j b_{i,j} bi,j,在状态 x x x时的最短长度,那么转移时就有
g j + 1 , y = m i n { g j , x + f b i , j , x , y } g_{j+1,y}=min\{g_{j,x}+f_{b_{i,j},x,y}\} gj+1,y=min{ gj,x+fbi,j,x,y}
但是会注意到 f i , s , t f_{i,s,t} fi,s,t之间的转移并不是一个单向的关系,会发现这是一个和最短路很类似的转移,我们考虑魔改一下SPFA。
我们先把 0 , 1 0,1 0,1加入队列,然后每次取出队头 x x x,我们把所有包含字符 x x x的 b i b_i bi都拿出来跑一次 g g g,如果这次跑出来的 g g g能够更新 f a i , s , t f_{a_i,s,t} fai,s,t,那么我们就把 a i a_i ai入队(如果之前 a i a_i ai不在队列中)。
我们视SPFA的复杂度为 O ( n 2 ) O(n^2) O(n2),记AC自动机状态数为 k k k,每做一次转移应该是 O ( ∣ b i ∣ k 3 ) O(|b_i|k^3) O(∣bi∣k3),那么这题中SPFA的复杂度应该就是 O ( G ∑ ∣ b i ∣ k 3 ) O(G\sum |b_i|k^3) O(G∑∣bi∣k3),实际上跑起来常数会很小,可以通过本题。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const ll N=105,inf=1e18;
ll G,n,m,a[N],f[N][N][N],g[N][52];
ll cnt,ch[N][2],fail[N];bool ed[N],v[N];
queue<int> q;vector<int> b[N],T[N];
void ins(ll n){
ll x=0;
for(ll i=1,c;i<=n;i++){
scanf("%lld",&c);
if(!ch[x][c])ch[x][c]=++cnt;
x=ch[x][c];
}
ed[x]=1;return;
}
void getfail(){
for(ll i=0;i<2;i++)
if(ch[0][i])q.push(ch[0][i]);
while(!q.empty()){
ll x=q.front();q.pop();
ed[x]|=ed[fail[x]];
for(ll i=0;i<2;i++){
if(ch[x][i]){
fail[ch[x][i]]=ch[fail[x]][i];
q.push(ch[x][i]);
}
else ch[x][i]=ch[fail[x]][i];
}
}
return;
}
bool solve(int i){
bool flag=0;
for(ll s=0;s<=cnt;s++){
if(ed[s])continue;
memset(g,0x3f,sizeof(g));g[0][s]=0;
for(ll j=0;j<b[i].size();j++){
for(ll x=0;x<=cnt;x++){
if(g[j][x]>=inf)continue;
for(ll y=0;y<=cnt;y++)
g[j+1][y]=min(g[j+1][y],g[j][x]+f[b[i][j]][x][y]);
}
}
for(ll x=0;x<=cnt;x++){
flag|=(g[b[i].size()][x]<f[a[i]][s][x]);
f[a[i]][s][x]=min(f[a[i]][s][x],g[b[i].size()][x]);
}
}
return flag;
}
void SPFA(){
q.push(0);q.push(1);v[0]=v[1]=1;
while(!q.empty()){
int x=q.front();q.pop();v[x]=0;
for(int i=0;i<T[x].size();i++){
int y=T[x][i];
if(solve(y)&&!v[a[y]])
q.push(a[y]),v[a[y]]=1;
}
}
return;
}
signed main()
{
scanf("%lld%lld%lld",&G,&n,&m);
for(ll i=1,k;i<=n;i++){
scanf("%lld%lld",&a[i],&k);
for(ll j=1,x;j<=k;j++){
scanf("%lld",&x),b[i].push_back(x);
T[x].push_back(i);
}
}
for(ll i=1,k;i<=m;i++){
scanf("%lld",&k);
ins(k);
}
getfail();ll k=0;
memset(f,0x3f,sizeof(f));
for(ll i=0;i<=cnt;i++){
if(ed[i])continue;
if(!ed[ch[i][0]])f[0][i][ch[i][0]]=1;
if(!ed[ch[i][1]])f[1][i][ch[i][1]]=1;
}
SPFA();
for(ll i=2;i<G;i++){
ll ans=inf;
for(ll x=0;x<=cnt;x++)
ans=min(ans,f[i][0][x]);
if(ans>=inf)puts("YES");
else printf("NO %lld\n",ans);
}
return 0;
}
边栏推荐
- 嵌入式 | 硬件转软件的几条建议
- Solution: Nan occurs in loss during model training
- 1528. rearrange strings
- Pytorch读入据集(典型数据集及自定义数据集两种模式)
- Ebanb B1 Bracelet brush firmware abnormal interrupt handling
- pm2 部署 nuxt3.js 项目
- “论解不了数独所以选择做个数独游戏这件事”
- 解决:jmeter5.5在win11下界面上的字特别小
- [quantitative investment] discrete Fourier transform to calculate array period
- I heard that you are still spending money to buy ppt templates from the Internet?
猜你喜欢

MySQL data (Linux Environment) scheduled backup

Alibaba Senior Software Testing Engineer recommends testers to learn -- Introduction to security testing

MySQL | view notes on Master Kong MySQL from introduction to advanced

玄铁E906移植----番外0:玄铁C906仿真环境搭建

4275. Dijkstra sequence

【LeetCode】541. Reverse string II

110. balanced binary tree recursive method

深入了解 border

“论解不了数独所以选择做个数独游戏这件事”

Target detection series fast r-cnn
随机推荐
学习太极创客 — ESP8226 (十三)OTA
荐书丨《好奇心的秘密》:一个针尖上可以站多少跳舞的小天使?
【LeetCode】387. 字符串中的第一个唯一字符
Yolox backbone -- implementation of cspparknet
Implementation process of tcpdump packet capturing
十二、所有功能实现效果演示
How does the tunnel mobile inspection track robot monitor 24 hours to ensure the safety of tunnel construction?
【LeetCode】387. First unique character in string
[noi Simulation Competition] geiguo and time chicken (structure)
uniapp 开发多端项目如何配置环境变量以及区分环境打包
Qingcloud based R & D cloud solution for geographic information enterprises
4274. 后缀表达式
【gdb调试工具】| 如何在多线程、多进程以及正在运行的程序下调试
2022.06.23 (traversal of lc_144,94145\
Determination of monocular and binocular 3D coordinates
【LeetCode】415. String addition
Become an IEEE student member
Matlab camera calibrator camera calibration
pm2 部署 nuxt3.js 项目
2022.6.13-6.19 AI行业周刊(第102期):职业发展