5073 [Lydsy1710月赛]小A的咒语
LINK:[Lydsy1710月赛]小A的咒语
每次给定两个串 要求从a串中选出x段拼成B串 能否做到。T组数据。
\(n\leq 100000,m\leq 100000,T\leq 10,x\leq 100\)
首先考虑贪心的从前往后匹配 若果当前匹配位置比之前还要远覆盖之前的 但是这样做会出现问题。
可能当前匹配的是之前匹配的后面的一段 也可能是之前的一段。
所以需要dp来解决这个后效性问题 设g[i][j]表示前i段个字符选出了j段所能拼成B串的最大长度。
有g[i][j]=g[i-1][j] 考虑匹配的时候 从i+1 和g[i][j]+1进行匹配。
为什么要这样做考虑g数组值小一点显然当前大一点的g数组比小一点的要优 给后面带来的结果不会更差。
由于第二维状态的存在也解决了上述 到底是匹配之前的还是匹配之后的问题。
考虑转移 枚举K 进行转移 f[i+k][j+1]=f[i][j]+k; 考虑这里的k取到最大值的时候对后面结果不会更差。
注意这里只能采用刷表法 因为填表的话还是不知道K是多少。
多组数据 注意清空。
const int MAXN=400010;
int n,k,m,ww,L,R,w1,w2;
int x[MAXN],y[MAXN],sa[MAXN],rk[MAXN],h[MAXN],c[MAXN];
int f[MAXN][21],Log[MAXN],g[100010][103];
char a[MAXN];
inline void SA()
{
    m=150;
	rep(1,m,i)c[i]=0;
    rep(1,n,i)++c[x[i]=a[i]];
    rep(1,m,i)c[i]+=c[i-1];
    rep(1,n,i)sa[c[x[i]]--]=i;
    for(int k=1;k<=n;k=k<<1)
    {
        int num=0;
        rep(n-k+1,n,i)y[++num]=i;
        rep(1,n,i)if(sa[i]>k)y[++num]=sa[i]-k;
        rep(1,m,i)c[i]=0;
        rep(1,n,i)++c[x[i]];
        rep(1,m,i)c[i]+=c[i-1];
        fep(n,1,i)sa[c[x[y[i]]]--]=y[i];
        rep(1,n,i)y[i]=x[i],x[i]=0;
        x[sa[1]]=num=1;
        rep(2,n,i)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?num:++num;
        if(n==num)break;
        m=num;
    }
    rep(1,n,i)rk[sa[i]]=i;
}
inline void get_height()
{
    int k=0;
    rep(1,n,i)
    {
        if(rk[i]==1)continue;
        if(k)--k;
        int j=sa[rk[i]-1];
        while(a[i+k]==a[j+k])++k;
        h[rk[i]]=k;
    }
    rep(2,n,i)
    {
        f[i-1][0]=h[i];
        Log[i]=Log[i>>1]+1;
    }
    rep(1,Log[n-1],j)
        rep(1,n-1-(1<<j)+1,i)
            f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
inline int LCP(int x,int y)
{
    if(x>w1||y>w2)return 0;
    x=rk[x];y=rk[y+w1+1];
    if(x>y)swap(x,y);--y;
    int z=Log[y-x+1];
    return min(f[x][z],f[y-(1<<z)+1][z]);
}
int main()
{
    freopen("1.in","r",stdin);
    int T;get(T);
	rep(2,300000,i)Log[i]=Log[i>>1]+1;
	while(T--)
	{
		get(w1);get(w2);int get(cc);
		gc(a);gc(a+w1+1);
		a[w1+1]='z'+1;a[w1+w2+2]='z'+2;
		n=w1+w2+1;
		SA();get_height();
		memset(g,0,sizeof(g));
		rep(0,w1,i)
		{
			rep(0,cc,j)
			{
				if(i>=1)g[i][j]=max(g[i-1][j],g[i][j]);
				int ww=LCP(i+1,g[i][j]+1);
				if(i+ww<=w1)g[i+ww][j+1]=max(g[i][j]+ww,g[i+ww][j+1]);
				//cout<<g[i+ww][j+1]<<endl;
			}
		}
		if(g[w1][cc]>=w2){puts("YES");}
		else puts("NO");
	}
    return 0;
}
5073 [Lydsy1710月赛]小A的咒语的更多相关文章
- 【bzoj5073】[Lydsy1710月赛]小A的咒语  后缀数组+倍增RMQ+贪心+dp
		题目描述 给出 $A$ 串和 $B$ 串,从 $A$ 串中选出至多 $x$ 个互不重合的段,使得它们按照原顺序拼接后能够得到 $B$ 串.求是否可行.多组数据. $T\le 10$ ,$|A|,|B| ... 
- [BZOJ5073][Lydsy1710月赛]小A的咒语
		bzoj description 你有一个\(A\)串和\(B\)串,你需要判断是否可以在\(A\)串中拆出\(x\)个互不相交的子串,使它们按顺序拼在一起可以组成\(B\)串. \(|A|,|B|\ ... 
- [BZOJ5073] [Lydsy1710月赛]小A的咒语 后缀数组+dp+贪心
		题目链接 首先这种题一看就是dp. 设\(dp[i][j]\)表示\(A\)序列中到\(i\)位之前,取了\(j\)段,在\(B\)中的最长的长度. 转移也比较简单 \[ dp[i][j] \to d ... 
- 【BZOJ5073】[Lydsy十月月赛]小A的咒语 DP(错解)
		[BZOJ5073][Lydsy十月月赛]小A的咒语 题解:沙茶DP,完全不用后缀数组. 用f[i][j]表示用了A的前i个字符,用了j段,最远能匹配到哪.因为显然我们能匹配到的地方越远越好,所以我们 ... 
- [BZOJ 5072][Lydsy1710月赛]小A的树
		传送门 \(\color{green}{solution}\) 嗯...其实我也不太会,所以大胆猜个结论吧(后来证了一下,然后放弃了...). 我们发现如果要使一个联通块的黑点数量为\(k\)的方案最 ... 
- BZOJ5072:[Lydsy1710月赛]小A的树(树形DP)
		Description BZOJ只是扔了个下载链接 Solution 设$f[x][i]$表示$x$点选中$i$个黑点的最小连通块. 设$g[x][i]$表示$x$点选中$i$个黑点的最大连通块. 转 ... 
- [BZOJ 5074][Lydsy1710月赛]小B的数字
		传送门 \(\color{green}{solution}\) 设 \[b_{i}=2^{w_{i}},sum= \sum_{i=1}^{n}{w_{i}}\] 则对于任意\(a_{i}\)都有 \[ ... 
- [Lydsy1710月赛] 小B的数字
		神TM 又又又又是构造题..... 很简单的化简就是,把2^k[i]都换成k[i] ,然后就可以得出 对于任意的i,k[i] * a[i] >= ∑k[]. 最优的构造肯定是使 k[i] = ... 
- bzoj 5072 [Lydsy1710月赛]小A的树——树形dp
		题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5072 发现对于每个子树,黑点个数确定时,连通块的大小取值范围一定是一段区间:所以考虑只最小化 ... 
随机推荐
- 关键字: this的使用
			1.可以调用的结构:属性.方法:构造器2.this调用属性.方法:this理解为:当前对象 或 当前正在创建的对象 2.1 在类的方法中,我们可以使用"this.属性"或" ... 
- P2034 选择数字——线性dp(单调队列优化)
			选择数字 题目描述 给定一行 \(n\) 个非负整数 \(a[1]...a[n]\) .现在你可以选择其中若干个数,但不能有超过 \(k\) 个连续的数字被选择.你的任务是使得选出的数字的和最大. 输 ... 
- lombok使用指南,代码极简工具
			我们的项目中会用到各种bean,比如vo,bo,dto等等,bean上的属性我们一般写get(),set()方法,整个java文件看起来很臃肿. 一.简介 我们今天介绍的lombok只用使用注解就可以 ... 
- mysql根据逗号分割的字符串去关联查询另外一个表的数据
			1.说明 在做显示数据的时候,一个字段会存那种逗号分割的字符串,那如何去根据逗号分割字符串去查询另一个表的数据呢? 首先我们查看一下需要显示的数据 select * from company wher ... 
- maven自动创建项目目录骨架
			方法一: 1:打开命令窗口 在要创建项目的路径下按住H2SIT ,然后点击右键 ,在弹出菜单中选择 在此处打开命令窗口(W) 2:目录创建 方法二: 
- Python3 迭代器深入解析
			第6章 函数 6.1 函数的定义和调用 6.2 参数传递 6.3 函数返回值 6.4 变量作用域 6.5 匿名函数(lambda) 6.6 递归函数 6.7 迭代器 6.8 生成器 6.9 装饰器 6 ... 
- 第七章:Android动画深入分析
			7.1 View动画 View动画的作用对象是View,它支持四种动画效果,分别是平移动画,缩放动画,旋转动画和透明动画. 帧动画也属于View动画,但是帧动画的表现形式和上面的四种变换效果不太一样. ... 
- layui :iframe 与 layer 的位置问题
			最近有个项目是用 Layui 搭的,但是在layer的使用上遇到了问题. 简单的说,在父页面声明layer,在子页面中的子页面用window.parent调用那个父页面的layer. 讲道理应该是和i ... 
- vue 应用 :关于 ElementUI 的 message 组件
			我们知道,这个东西的基本用法是这样的: this.$message({ message: '恭喜你,这是一条成功消息', type: 'success' }); 但是我觉得这样还是有点麻烦,所以我决定 ... 
- three.js 数学方法之Box3
			从今天开始郭先生就会说一下three.js 的一些数学方法了,像Box3.Plane.Vector3.Matrix3.Matrix4当然还有欧拉角和四元数.今天说一说three.js的Box3方法(B ... 
