题目: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. vue项目打包之后原本好的样式变得不好了的原因分析

    这个主要是打包的过程将所有的css文件进行归类压缩,导致原先其他文件里的样式对当前的产生了影响,应该有同样的类名了.怎么改?要么改类名,要么用scope,scss的写法.

  2. bzoj 4161 Shlw loves matrixI——常系数线性齐次递推

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4161 还是不能理解矩阵…… 关于不用矩阵理解的方法:https://blog.csdn.ne ...

  3. php7和MongoDB插入并读取数据

    php7和MongoDB插入并读取数据 代码如下: <?php $manager = new MongoDB\Driver\Manager("mongodb://localhost:2 ...

  4. python接口自动化测试三十六:数据驱动参数化之paramunittest

    官方文档1.官方文档地址:https://pypi.python.org/pypi/ParamUnittest/2.github源码下载地址:https://github.com/rik0/Param ...

  5. shell zip和unzip压缩和解压,压缩效率

    1.把/home目录下面的mydata目录压缩为mydata.zip zip -r mydata.zip mydata #压缩mydata目录zip -r mydata.zip ./*txt #压缩当 ...

  6. mac bash上显示git分支与状态

    主要实现 显示当前路径 显示当前所在分支 显示当前修改状态 = 表示一个干净的分支 ~ 表示文件有改动 # 表示已commit 但未 push 通过网上搜索和自己根据实际需要修改的代码如下: .bas ...

  7. python 字典(dictionary)一些方法

    1.python 字典(Dictionary) keys() 函数以列表返回一个字典所有的键. keys()语法: dict.keys() 2.setdefault()方法 python字典setde ...

  8. nginx之域名重定向

    一般网站默认的访问端口为80,当多个域名指向同一个服务器IP时,可以nginx进行重定向,分别指向不同的目的地址或其他主机. 在nginx目录下的conf/vhost子目录下建两个conf文件,hos ...

  9. Python的基本类型(list,tuple)

    Python的基本类型(list,tuple) 一列表: 1.列表是Python基础的数据类型之一,其他语言也有类似的数据类型,比如js中的数组,java中的数组等,它是以[]括起来 ,每个元素用', ...

  10. Golang 读书

    var a map[string] int  类似Key\Value var( 多个变量,避免多次声明var ) 声明变量 多重赋值 i,j=j,i 匿名变量 _ literal 字面常量   con ...