题目: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的更多相关文章

  1. 异或序列 [set优化DP]

    也许更好的阅读体验 \(\mathcal{Description}\) 有一个长度为 \(n\)的自然数序列 \(a\),要求将这个序列分成至少 \(m\) 个连续子段 每个子段的价值为该子段的所有数 ...

  2. 后缀自动机&序列自动机综合

    好像序列自动机还没有写过- 串长为n的串共有n+1个节点,除了串中的n个节点,还有一个空的根节点放在串首.每个节点至多有26条出边,每条边连向它之后的第一个字符. 串中的任意一个子序列对应了一条根到某 ...

  3. Codeforces 1050D Three Religions (dp+序列自动机)

    题意: 给一个1e5的串str,然后有三个起始空串,不超过1000次操作,对三个字符串的一个尾部加一个字符或者减一个字符,保证每个字符不会超过250 每次操作之后询问你这三个串是不是可以组成str的子 ...

  4. 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做

    题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...

  5. 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)

    [BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...

  6. Subsequence(序列自动机模板题)

    题目链接:https://nanti.jisuanke.com/t/38232 题目大意:给你一个字符串,然后再给你m个字符串,然后问你在第一个字符串中不连续的子串能不能构成输入的子串. 具体思路:构 ...

  7. 【机器学习】支持向量机(SVM)的优化算法——序列最小优化算法(SMO)概述

    SMO算法是一一种启发式算法,它的基本思路是如果所有变量的解的条件都满足最优化问题的KKT条件,那么这个最优化问题的解就得到了.因为KKT条件是该优化问题的充分必要条件. 整个SMO算法包括两个部分: ...

  8. BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心

    题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...

  9. 牛客小白月赛12J(序列自动机)

    题目链接:https://ac.nowcoder.com/acm/contest/392/J 题目大意:给一个字符串s,然后在给出n个其他的字符串,判断每个字符串是否为s的子序列. 例: 输入: no ...

随机推荐

  1. Apache搭建http网站服务器入门教程

    Apache搭建http网站服务器入门教程 准备工具 一台带有Linux系统的主机,这里使用CentOS 7.1 64位系统 一个备案过的域名,这里使用www.hellopage.cn 一台可以访问网 ...

  2. Java反射之方法反射demo

    package reflect; import java.lang.reflect.Method; public class ClassDemo3 { public static void main( ...

  3. C# 后台报错输出到日志

    1.C# 方法 /// <summary> /// 异常处理 /// </summary> /// <returns></returns> public ...

  4. MySQL中truncate误操作后的数据恢复案例

    MySQL中truncate误操作后的数据恢复案例 这篇文章主要介绍了MySQL中truncate误操作后的数据恢复案例,主要是要从日志中定位到truncate操作的地方然后备份之前丢失的数据,需要的 ...

  5. js对象传到后台ACTION使用

    需的包 <script type="text/javascript" src="s"></script>gson-1.2.3.jar谷歌 ...

  6. 抓包工具charles下载安装(MAC版)

    什么是charles? charles是一个HTTP代理服务器,HTTP监视器,反转代理服务器,当浏览器连接Charles的代理访问互联网时,Charles可以监控浏览器发送和接收的所有数据.它允许一 ...

  7. 百度网盘不限速-Motrix

    目录: Windows 下使用  Motrix Mac 下使用 BaiduNetdiskPlugin-macOS Mac 下使用 Motrix Windows 系统  Motrix 1. Google ...

  8. sourcetree配置gitlab

    一.准备 1.安装git,下载地址:https://git-scm.com/download 安装教程百度一下      git客户端(1.产生gitlab服务端和本地git相互传输时所需要校验的私钥 ...

  9. UVALive 4992 Jungle Outpost(半平面交判存)

    Jungle Outpost Time limit: 15.000 seconds Description There is a military base lost deep in the jung ...

  10. windows10图形化连接CentOS7

    前提:CentOS已经安装图形化,安装教程可以百度 [root@localhost ~]# cat /etc/redhat-release CentOS Linux release (Core) 安装 ...