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. Poi中getPhysicalNumberOfCells 与 getLastCellNum的差异

    getPhysicalNumberOfCells 与 getLastCellNum的区别 用org.apache.poi的包做excel导入,无意间发明若是excel文件中有空列,空列后面的数据全部读 ...

  2. asp.net mvc Route路由映射.html后缀 404错误

    [HttpGet] [Route("item/{id:long:min(1)}.html")] 首先RouteConfig配置文件RegisterRoutes方法添加以下代码: r ...

  3. program发展史及以后预测

    三个阶段:第一个阶段是1950年代到1960年代,是程序设计阶段,基本是个体手工劳动的生产方式.这个时期,一个程序是为一个特定的目的而编制的,软件的通用性是很有限的,软件往往带有强烈的个人色彩.早期的 ...

  4. leetcode算法总结

    算法思想 二分查找 贪心思想 双指针 排序 快速选择 堆排序 桶排序 搜索 BFS DFS Backtracking 分治 动态规划 分割整数 矩阵路径 斐波那契数列 最长递增子序列 最长公共子系列 ...

  5. 在写一个iOS应用之前必须做的7件事(附相关资源)

    本文由CocoaChina--不再犹豫(tao200610704@126.com)翻译 作者:@NIkant Vohra 原文:7 Things you must absolutely do befo ...

  6. Pandas:SettingWithCopyWarning

    当我为数据增加新的列的时候,Pandas一直报错:SettingWithCopyWarning 这个问题没有很好地解决方法,因为这个问题也无关大碍,不让Pandas报错就行了. 解决方法: pd.op ...

  7. VS2010制作安装程序

    转自(http://blog.csdn.net/wenmang1977/article/details/7733685) 序 前些天想写一下制作安装程序,由于要写的内容比较多,一拖再拖,不过坚持就是胜 ...

  8. SQL 按照多个字段为标准的重复数据处理

    表结构:T1 id int Uncheckedname nchar(10) Checkedvalue nchar(10) Checked 数据: 1 a a1 2 a a1 3 b b1 4 b b2 ...

  9. eclipse背景设置什么颜色缓解眼睛疲劳之一

    Eclipse操作界面默认颜色为白色.对于我们长期使用电脑编程的人来说,白色很刺激我们的眼睛,如果把颜色改成绿色的颜色就会缓解眼睛的疲劳. 设置方法如下: 1.打开window->Prefere ...

  10. jQuery Ajax同步参数导致浏览器假死怎么办

    俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下.   事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的 ...