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. session.资料

    1. HttpSessionListener https://www.cnblogs.com/diewufeixian/p/4221747.html 2. 3. 4. 5.

  2. A4纸网页打印 html网页页面的宽度设置成多少

    A4纸竖向打印,html网页页面的宽度设置成多少?这个问题是我们大家所疑惑的,于是网上搜集整理下,希望可以帮助你们 最近开发项目时遇到了网页打印的问题,这是问题之二,打印宽度设置 在公制长度单位与屏幕 ...

  3. 前端构建大法 Gulp 系列

    参考: 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp ...

  4. SpringMvc中的校验框架@valid和@validation的概念及相关使用 和BindingResult bindingResult

    1.比较 @Valid是使用hibernate validation的时候使用 @Validated 是只用spring  Validator 校验机制使用\ 2.实现 其中,@valid,java的 ...

  5. 设计模式--单例模式C++实现

    单例模式C++实现 1描述: 单例模式,又称单件模式. 定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 2具体类图描述: 2.1 StartUML内部生成模式类图 该类图由S ...

  6. Highcharts 基本曲线图;Highcharts 带有数据标签曲线图表;Highcharts 异步加载数据曲线图表

    Highcharts 基本曲线图 实例 文件名:highcharts_line_basic.htm <html> <head> <meta charset="U ...

  7. notepad配合正则表达式处理文本

    <option value="irs01.com">irs01.com</option><option value="hdslb.com&q ...

  8. 037——VUE中表单控件处理之表单修饰符:lazy/number/trim

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

  9. zoj1654

    题解: 对于每一联通的x,y 检点 然后交叉的连边 然后二分图 代码: #include<cstdio> #include<cstring> #include<cmath ...

  10. LeetCode OJ:Burst Balloons(击破气球)

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...