bzoj

description

你有一个\(A\)串和\(B\)串,你需要判断是否可以在\(A\)串中拆出\(x\)个互不相交的子串,使它们按顺序拼在一起可以组成\(B\)串。

\(|A|,|B|\le10^5,x\le100\)

sol

设\(f_{i,j}\)表示已经使用了\(i\)个\(A\)的子串,\(A\)已经使用到了\(j\)位置时\(B\)串中的最长匹配的长度,每次转移的时候显然回取\(A\)串中的\(j+1\)位置和\(B\)串中的\(f_{i,j}+1\)位置的\(lcp\)进行转移,再做一个前缀\(\max\)就好了。

\(lcp\)用后缀数组做到\(O(n\log n)-O(1)\),复杂度\(O(T(n\log n+nx))\)

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 2e5+5;
int T,n,m,K,len,val[N],t[N],x[N],y[N],SA[N],Rank[N],Height[20][N],lg[N],f[2][N];
char a[N],b[N];
bool cmp(int i,int j,int k){return y[i]==y[j]&&y[i+k]==y[j+k];}
void getSA(){
int m=30;
for (int i=0;i<=m;++i) t[i]=0;
for (int i=1;i<=len;++i) ++t[x[i]=val[i]];
for (int i=1;i<=m;++i) t[i]+=t[i-1];
for (int i=len;i;--i) SA[t[x[i]]--]=i;
for (int k=1;k<=len;k<<=1){
int p=0;
for (int i=0;i<=m;++i) y[i]=0;
for (int i=len-k+1;i<=len;++i) y[++p]=i;
for (int i=1;i<=len;++i) if (SA[i]>k) y[++p]=SA[i]-k;
for (int i=0;i<=m;++i) t[i]=0;
for (int i=1;i<=len;++i) ++t[x[y[i]]];
for (int i=1;i<=m;++i) t[i]+=t[i-1];
for (int i=len;i;--i) SA[t[x[y[i]]]--]=y[i];
swap(x,y);x[SA[1]]=p=1;
for (int i=2;i<=len;++i) x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p;
if (p>=len) break;m=p;
}
for (int i=1;i<=len;++i) Rank[SA[i]]=i;
for (int i=1,j=0;i<=len;++i){
if (j) --j;
while (val[i+j]==val[SA[Rank[i]-1]+j]) ++j;
Height[0][Rank[i]]=j;
}
for (int i=2;i<=len;++i) lg[i]=lg[i>>1]+1;
for (int j=1;j<=lg[len];++j)
for (int i=1;i+(1<<j)-1<=len;++i)
Height[j][i]=min(Height[j-1][i],Height[j-1][i+(1<<j-1)]);
}
int lcp(int i,int j){
i=Rank[i],j=Rank[j];if (i>j) swap(i,j);
++i;int k=lg[j-i+1];
return min(Height[k][i],Height[k][j-(1<<k)+1]);
}
int main(){
T=gi();while (T--){
n=gi();m=gi();K=gi();scanf("%s",a+1);scanf("%s",b+1);
memset(Rank,0,sizeof(Rank));
for (int i=1;i<=n;++i) val[i]=a[i]-'a'+1;
for (int i=1;i<=m;++i) val[n+1+i]=b[i]-'a'+1;
val[n+1]=27;val[n+1+m+1]=0;len=n+m+1;getSA();
memset(f[0],0,sizeof(f[0]));
for (int i=1;i<=K;++i){
int now=i&1,pre=now^1;
memset(f[now],0,sizeof(f[now]));
for (int j=0;j<n;++j){
int gg=lcp(j+1,n+1+f[pre][j]+1);
f[now][j+gg]=max(f[now][j+gg],f[pre][j]+gg);
}
for (int j=1;j<=n;++j) f[now][j]=max(f[now][j],f[now][j-1]);
}
puts(f[K&1][n]==m?"YES":"NO");
}
return 0;
}

[BZOJ5073][Lydsy1710月赛]小A的咒语的更多相关文章

  1. [BZOJ5073] [Lydsy1710月赛]小A的咒语 后缀数组+dp+贪心

    题目链接 首先这种题一看就是dp. 设\(dp[i][j]\)表示\(A\)序列中到\(i\)位之前,取了\(j\)段,在\(B\)中的最长的长度. 转移也比较简单 \[ dp[i][j] \to d ...

  2. 5073 [Lydsy1710月赛]小A的咒语

    LINK:[Lydsy1710月赛]小A的咒语 每次给定两个串 要求从a串中选出x段拼成B串 能否做到.T组数据. \(n\leq 100000,m\leq 100000,T\leq 10,x\leq ...

  3. 【bzoj5073】[Lydsy1710月赛]小A的咒语 后缀数组+倍增RMQ+贪心+dp

    题目描述 给出 $A$ 串和 $B$ 串,从 $A$ 串中选出至多 $x$ 个互不重合的段,使得它们按照原顺序拼接后能够得到 $B$ 串.求是否可行.多组数据. $T\le 10$ ,$|A|,|B| ...

  4. 【BZOJ5073】[Lydsy十月月赛]小A的咒语 DP(错解)

    [BZOJ5073][Lydsy十月月赛]小A的咒语 题解:沙茶DP,完全不用后缀数组. 用f[i][j]表示用了A的前i个字符,用了j段,最远能匹配到哪.因为显然我们能匹配到的地方越远越好,所以我们 ...

  5. [BZOJ 5072][Lydsy1710月赛]小A的树

    传送门 \(\color{green}{solution}\) 嗯...其实我也不太会,所以大胆猜个结论吧(后来证了一下,然后放弃了...). 我们发现如果要使一个联通块的黑点数量为\(k\)的方案最 ...

  6. BZOJ5072:[Lydsy1710月赛]小A的树(树形DP)

    Description BZOJ只是扔了个下载链接 Solution 设$f[x][i]$表示$x$点选中$i$个黑点的最小连通块. 设$g[x][i]$表示$x$点选中$i$个黑点的最大连通块. 转 ...

  7. [BZOJ 5074][Lydsy1710月赛]小B的数字

    传送门 \(\color{green}{solution}\) 设 \[b_{i}=2^{w_{i}},sum= \sum_{i=1}^{n}{w_{i}}\] 则对于任意\(a_{i}\)都有 \[ ...

  8. [Lydsy1710月赛] 小B的数字

    神TM 又又又又是构造题..... 很简单的化简就是,把2^k[i]都换成k[i] ,然后就可以得出 对于任意的i,k[i] * a[i] >= ∑k[]. 最优的构造肯定是使  k[i] = ...

  9. bzoj 5072 [Lydsy1710月赛]小A的树——树形dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5072 发现对于每个子树,黑点个数确定时,连通块的大小取值范围一定是一段区间:所以考虑只最小化 ...

随机推荐

  1. winmm.dll获取和设置声音

    [DllImport("winmm.dll")] private static extern int waveOutGetVolume(IntPtr hwo, out uint d ...

  2. C++双向循环链表实现

    双向循环链表C++实现 1.单链表: 结构图: 2.双向链表: 3.双向循环链表: 对于本程序中,则是给定一个_head  头结点,而不是指针,因为这样更加方便避免一些空判断问题 /* 版权信息:狼 ...

  3. 《深入理解mybatis原理7》 MyBatis的二级缓存的设计原理

    <深入理解mybatis原理> MyBatis的二级缓存的设计原理 MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能.本文将全面分 ...

  4. 从工程角度看C++观察者模式中的接口是否需要提供默认的实现

    在C++中,我们会经常用到观察者模式(回调模式,Delegate模式等,意思都一样),比如当Source中的某个参数发生了变化时,我们通过观察者模式进行回调通知,下面是一个例子: class Sour ...

  5. Project facet Java 1.8 is not supported by target runtime Apache Tomcat v7.0.

    找到项目下的“.settings”

  6. centos7&redhat 之 firewalld 详细介绍配置

    firewalld和iptables的关系 firewalld自身并不具备防火墙的功能,而是和iptables一样需要通过内核的netfilter来实现,也就是说firewalld和iptables一 ...

  7. log4j 日志详解

    # 以下是rootLogger的配置,子类默认继承,但是子类重写下面配置=rootLogger+自己配置,我晕#输出到控制台 log4j.appender.console=org.apache.log ...

  8. 032——VUE中表单控件处理之复选框的处理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. LeetCode OJ:Jump Game II(跳跃游戏2)

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  10. vue 插件(Sublime Text 3 常用插件以及安装方法)(转)

    使用Package Control组件安装 也可以安装package control组件,然后直接在线安装:按Ctrl+` 调出console粘贴以下代码到底部命令行并回车: { import url ...