CF 1150 D Three Religions——序列自动机优化DP
题目:http://codeforces.com/contest/1150/problem/D
老是想着枚举当前在给定字符串的哪个位置,以此来转移。
所以想对三个串分别建 trie 树,然后求出三个trie树上各选一个点的答案。那么从“在三个trie树的根,在给定字符串的0位置”开始扩展。
当然 TLE 了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
const int N=1e5+,M=;
int n,m,tot=,nw[],fa[M],c[M][],fl[M],q2[M];
char s[N];
struct Dt{
int x,y,z;
Dt(int x=,int y=,int z=):x(x),y(y),z(z) {}
bool operator< (const Dt &b)const
{
if(x!=b.x)return x<b.x;
if(y!=b.y)return y<b.y; return z<b.z;
}
bool operator== (const Dt &b)const
{return x==b.x&&y==b.y&&z==b.z;}
}qr[M],I;
struct Node{
Dt a;int ps;
Node(Dt a=I,int p=):a(a),ps(p) {}
bool operator< (const Node &b)const
{return a<b.a;}
};
queue<Node> q;
map<Dt,bool> mp;
void add(int &x,int w)
{
if(c[x][w])x=c[x][w];////if!!!!!
else{ c[x][w]=++tot; fa[tot]=x; x=tot;}
}
void get_fl(int rt)
{
int he=,tl=;
for(int i=;i<;i++)
if(c[rt][i])fl[c[rt][i]]=rt,q2[++tl]=c[rt][i];
else c[rt][i]=rt;
while(he<tl)
{
int k=q2[++he],pr=fl[k];
for(int i=;i<;i++)
if(c[k][i])fl[c[k][i]]=c[pr][i],q2[++tl]=c[k][i];
else c[k][i]=c[pr][i]; }
}
void cz(Dt cr,int ps)
{
for(int x=cr.x;x;x=fl[x])
for(int y=cr.y;y;y=fl[y])
for(int z=cr.z;z;z=fl[z])
if(!mp[cr]){mp[cr]=; q.push(Node(cr,ps));}
else return;
}
int main()
{
scanf("%d%d",&n,&m); scanf("%s",s+);
nw[]=; nw[]=; nw[]=;
char op,w;int d;
for(int i=;i<=m;i++)
{
cin>>op; scanf("%d",&d);
if(op=='+'){cin>>w;add(nw[d],w-'a');}
else nw[d]=fa[nw[d]];
qr[i]=Dt(nw[],nw[],nw[]);
}
for(int i=;i<=;i++)get_fl(i);
Dt cr=Dt(,,); mp[cr]=; q.push(Node(cr,));
while(q.size())
{
Node k=q.front();q.pop();
if(k.ps==n)continue;
k.ps++; q.push(k); int w=s[k.ps]-'a';
cr=k.a; cr.x=c[cr.x][w]; cz(cr,k.ps);
cr=k.a; cr.y=c[cr.y][w]; cz(cr,k.ps);
cr=k.a; cr.z=c[cr.z][w]; cz(cr,k.ps);
}
for(int i=;i<=m;i++)
puts(mp.count(qr[i])?"YES":"NO");
return ;
}
给定字符串的一个位置可能使得三个串都不能扩展。所以考虑不枚举字符串的每个位置来转移,而是做一个序列自动机。
令 dp[i][j][k] 表示三个地区分别匹配了前 i 、j、k 个字符的“最靠前位置”,如果值==n+1说明无解。
那么就可以使用序列自动机实现 2503 的DP了。就是 dp[i][j][k] = min( nxt[ dp[i-1][j][k] ][ c1[i] ] , nxt[ dp[i][j-1][k] ][ c2[j] ] , nxt[ dp[i][j][k-1] ][ c3[k] ] ) 。
对于一个询问,如果是 ' - ' ,DP数组不用改动。如果是 ' + ' ,固定该维, 2502 做一下DP即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mn(int a,int b){return a<b?a:b;}
const int N=1e5+,M=,K=;
int n,lst[K],nxt[N][K],dp[M][M][M],l0,l1,l2;
char s[N];int c0[M],c1[M],c2[M];
int main()
{
n=rdn(); int Q=rdn();
scanf("%s",s+);
for(int i=;i<K;i++)
lst[i]=nxt[n+][i]=n+;
for(int i=n;i>=;i--)
{
for(int j=;j<K;j++) nxt[i][j]=lst[j];
if(i)lst[s[i]-'a']=i;
}
char op;int x,w;
while(Q--)
{
cin>>op; x=rdn()-;
if(op=='+')
{
cin>>op; w=op-'a';
if(x==)
{
c0[++l0]=w;
for(int i=;i<=l1;i++)
for(int j=;j<=l2;j++)
{
dp[l0][i][j]=nxt[dp[l0-][i][j]][w];
if(i)dp[l0][i][j]=
Mn(dp[l0][i][j],nxt[dp[l0][i-][j]][c1[i]]);//i not l1
if(j)dp[l0][i][j]=
Mn(dp[l0][i][j],nxt[dp[l0][i][j-]][c2[j]]);
}
}
if(x==)
{
c1[++l1]=w;
for(int i=;i<=l0;i++)
for(int j=;j<=l2;j++)
{
dp[i][l1][j]=nxt[dp[i][l1-][j]][w];
if(i)dp[i][l1][j]=
Mn(dp[i][l1][j],nxt[dp[i-][l1][j]][c0[i]]);
if(j)dp[i][l1][j]=
Mn(dp[i][l1][j],nxt[dp[i][l1][j-]][c2[j]]);
}
}
if(x==)
{
c2[++l2]=w;
for(int i=;i<=l0;i++)
for(int j=;j<=l1;j++)
{
dp[i][j][l2]=nxt[dp[i][j][l2-]][w];
if(i)dp[i][j][l2]=
Mn(dp[i][j][l2],nxt[dp[i-][j][l2]][c0[i]]);
if(j)dp[i][j][l2]=
Mn(dp[i][j][l2],nxt[dp[i][j-][l2]][c1[j]]);
}
}
}
else
{
if(x==)l0--; if(x==)l1--; if(x==)l2--;
}
puts(dp[l0][l1][l2]<=n?"YES":"NO");
}
return ;
}
CF 1150 D Three Religions——序列自动机优化DP的更多相关文章
- 异或序列 [set优化DP]
也许更好的阅读体验 \(\mathcal{Description}\) 有一个长度为 \(n\)的自然数序列 \(a\),要求将这个序列分成至少 \(m\) 个连续子段 每个子段的价值为该子段的所有数 ...
- 后缀自动机&序列自动机综合
好像序列自动机还没有写过- 串长为n的串共有n+1个节点,除了串中的n个节点,还有一个空的根节点放在串首.每个节点至多有26条出边,每条边连向它之后的第一个字符. 串中的任意一个子序列对应了一条根到某 ...
- Codeforces 1050D Three Religions (dp+序列自动机)
题意: 给一个1e5的串str,然后有三个起始空串,不超过1000次操作,对三个字符串的一个尾部加一个字符或者减一个字符,保证每个字符不会超过250 每次操作之后询问你这三个串是不是可以组成str的子 ...
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)
[BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...
- Subsequence(序列自动机模板题)
题目链接:https://nanti.jisuanke.com/t/38232 题目大意:给你一个字符串,然后再给你m个字符串,然后问你在第一个字符串中不连续的子串能不能构成输入的子串. 具体思路:构 ...
- 【机器学习】支持向量机(SVM)的优化算法——序列最小优化算法(SMO)概述
SMO算法是一一种启发式算法,它的基本思路是如果所有变量的解的条件都满足最优化问题的KKT条件,那么这个最优化问题的解就得到了.因为KKT条件是该优化问题的充分必要条件. 整个SMO算法包括两个部分: ...
- BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- 牛客小白月赛12J(序列自动机)
题目链接:https://ac.nowcoder.com/acm/contest/392/J 题目大意:给一个字符串s,然后在给出n个其他的字符串,判断每个字符串是否为s的子序列. 例: 输入: no ...
随机推荐
- The Tree-planting Day and Simple Disjoint Sets
First I have to say: I have poor English. I am too young, too simple, sometimes naïve. It was tree-p ...
- cython安装、使用
cython安装.使用 原创 2012年09月27日 17:25:11 8436 0 0 一.cython 在linux(ubuntu)下安装 sudo apt-get install cython ...
- 像这样玩C#【转】,觉得文章写的不错就转来啦!版权不在我
我们玩技术,不是被技术玩.Coding是快乐的,而非苦逼的..Net/C# 这个神器竟然天天有人吐槽.看不下去鸟. 在top10语言中,C#是最优美的语言,没有之一.在top10语言中,C#所可用的标 ...
- hbase 1.4 部署
centos 7 部署 hbase 1.4.11 版本 在部署 hbase 前,首先安装好 jdk 1.7 和 zookeeper 3.4.14 软件. 部署 zookeeper 软件,可以参考 zk ...
- 浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)(转)
引子 STM32的硬件I2C很多人都对它望而却步.因为很多电工都说,STM32 硬件 I2C有BUG.不稳定.死机等等……最后都使用GPIO模拟I2C. 的确,模拟I2C好用.但是在我看来在一个72M ...
- 深入浅出HashMap
/** *@ author ViVi *@date 2014-6-11 */ Hashmap是一种非常常用的.应用广泛的数据类型,最近研究到相关的内容,就正好复习一下.希望通过仪器讨论.共同提高~ 1 ...
- Iconv作用以及安装问题解决
当我们在使用Window操作系统的时候,可能使用最多的文本格式就是txt了,但是当我们将Window平台下的txt文本文档拷贝到Linux平台下查看时,发现原来的中文全部变成了乱码.没错, 引起这个结 ...
- CentOS下Java的安装与环境配置
网上的文章很多,但我还是不知道下次需要看谁的,或是给朋友推荐谁的,索性我都整理出来,方便下次需要的时候能很快的看到或是给朋友链接.两种安装方式:解压安装和包安装 1.安装前检查: 因为安 ...
- iis 跨域设置多域名
首先下载 https://www.iis.net/downloads/microsoft/url-rewrite 在最下方 然后在Web.config 文件里面 <configuration&g ...
- laravel打印查询的sql
public function __construct( ){ $log = DB :: listen( function( $sql ){ echo $sql; } ); }