[BZOJ5073] [Lydsy1710月赛]小A的咒语 后缀数组+dp+贪心
首先这种题一看就是dp。
设\(dp[i][j]\)表示\(A\)序列中到\(i\)位之前,取了\(j\)段,在\(B\)中的最长的长度。
转移也比较简单
dp[i][j] \to dp[i+k][j+1] \quad a[i+1..i+k]=b[dp[i][j]..dp[i][j]+k]
\]
但是这样做的复杂度肯定不行。
发现有一个贪心的思路,因为既然我这里已经占用了一次次数了,那么肯定要尽量地多在B中匹配才好。
所以这里的\(k\)可以直接取到\(LCP(a[i+1],b[dp[i][j]+1])\)。中间的点可以直接跳过,不用转移过去。
#include<bits/stdc++.h>
using namespace std;
#define fec(i,x,y) (int i=head[x],y=g[i].to;i;i=g[i].ne,y=g[i].to)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define fi first
#define se second
#define pb push_back
template<typename I>inline void read(I&x){int f=0,c;while(!isdigit(c=getchar()))c=='-'?f=1:0;x=c&15;while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);f?x=-x:0;}
template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;}
template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;}
typedef long long ll;typedef unsigned long long ull;typedef std::pair<int,int>pii;
const int N=2e5+7,M=100+7,LOG=20;
int T,n,m,p,ans;char a[N],b[N],s[N];
int dp[N][M];
int sa[N],rk[N],sec[N],tax[N],h[N];
inline void Make_SA(char*s,int n){
int m=26,*rnk=rk,*sc=sec;
for(int i=1;i<=m;++i)tax[i]=0;
for(int i=1;i<=n;++i)tax[rnk[i]=s[i]]++;
for(int i=1;i<=m;++i)tax[i]+=tax[i-1];
for(int i=n;i;--i)sa[tax[rnk[i]]--]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
for(int i=n-k+1;i<=n;++i)sc[++p]=i;
for(int i=1;i<=n;++i)if(sa[i]>k)sc[++p]=sa[i]-k;
for(int i=1;i<=m;++i)tax[i]=0;
for(int i=1;i<=n;++i)tax[rnk[sc[i]]]++;
for(int i=1;i<=m;++i)tax[i]+=tax[i-1];
for(int i=n;i;--i)sa[tax[rnk[sc[i]]]--]=sc[i];
swap(rnk,sc);p=rnk[sa[1]]=1;
for(int i=2;i<=n;++i)rnk[sa[i]]=(sc[sa[i]]==sc[sa[i-1]]&&sc[sa[i]+k]==sc[sa[i-1]+k]?p:++p);
if(p>=n)break;else m=p;
}
for(int i=1;i<=n;++i)rk[sa[i]]=i;
}
inline void Make_h(char*s,int n){
for(int i=1,f=0;i<=n;++i){
if(f)f--;int j=sa[rk[i]-1];
while(i+f<=n&&j+f<=n&&s[i+f]==s[j+f])++f;
h[rk[i]]=f;
}
}
int f[N][LOG];
inline void RMQ_init(int n){
for(int i=1;i<=n;++i)f[i][0]=h[i];
for(int j=1;(1<<j)<=n;++j)
for(int i=1;i+(1<<j)-1<=n;++i)
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
inline int Min(int l,int r){int k=__lg(r-l+1);return min(f[l][k],f[r-(1<<k)+1][k]);}
inline int LCP(int x,int y,int n=::n+m){if(x==y)return n-x+1;x=rk[x],y=rk[y];if(x>y)swap(x,y);return Min(x+1,y);}
inline void DP(){
for(int i=0,k;i<n;++i)
for(int j=0;j<=p;++j)
SMAX(dp[i+1][j],dp[i][j]),
k=min(n-i,LCP(i+1,dp[i][j]+n+1)),
j<p&&SMAX(dp[i+k][j+1],dp[i][j]+k);
}
inline void CSH(){
memset(dp,0,sizeof(dp));
ans=0;
}
int main(){
#ifdef hzhkk
freopen("hkk.in","r",stdin);
#endif
read(T);
while(T--){
CSH();
read(n),read(m),read(p);
scanf("%s%s",a+1,b+1);
for(int i=1;i<=n;++i)s[i]=a[i]-'a'+1;
for(int i=1;i<=m;++i)s[i+n]=b[i]-'a'+1;
Make_SA(s,n+m);Make_h(s,n+m);
RMQ_init(n+m);
DP();
for(int i=1;i<=p;++i)SMAX(ans,dp[n][i]);
if(ans>=m)printf("YES\n");
else printf("NO\n");
}
}
[BZOJ5073] [Lydsy1710月赛]小A的咒语 后缀数组+dp+贪心的更多相关文章
- 【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|\ ...
- 5073 [Lydsy1710月赛]小A的咒语
LINK:[Lydsy1710月赛]小A的咒语 每次给定两个串 要求从a串中选出x段拼成B串 能否做到.T组数据. \(n\leq 100000,m\leq 100000,T\leq 10,x\leq ...
- 【BZOJ5073】[Lydsy十月月赛]小A的咒语 DP(错解)
[BZOJ5073][Lydsy十月月赛]小A的咒语 题解:沙茶DP,完全不用后缀数组. 用f[i][j]表示用了A的前i个字符,用了j段,最远能匹配到哪.因为显然我们能匹配到的地方越远越好,所以我们 ...
- [bzoj1692][Usaco2007 Dec]队列变换_后缀数组_贪心
队列变换 bzoj-1692 Usaco-2007 Dec 题目大意:给定一个长度为$n$的字符串.每次从头或尾取出一个字符加到另一个字符串里.要求变换后生成的字符串字典序最小,求字典序最小的字符串. ...
- [bzoj4278][ONTAK2015]Tasowanie_后缀数组_贪心
Tasowanie bzoj-4278 ONTAK-2015 题目大意:给定两个字符串,求两个字符串二路归并之后生成的字典序最小的字符串是什么. 注释:$1\le len_1,len_2\le 2\c ...
- [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}\)都有 \[ ...
随机推荐
- Python3解leetcode First Bad Version
问题描述: You are a product manager and currently leading a team to develop a new product. Unfortunately ...
- web css
CSS圆角——透明圆角化背景图片 序言:第一章中我介绍了最基本的纯CSS圆角框的实现原理,并给出Demo,在本章中会对上一个模型作一些新的创新,实现将背景图片透明圆角化.并给出一些漂亮的通用演示效果. ...
- ConcurrentModificationException异常
介绍一个我今天在开发中遇到的异常:ConcurrentModificationException异常,当然它是一个非受检的异常,也就是运行时异常. 当我们在遍历集合对象的时候,不能够将集合删除.最佳实 ...
- PHP RSA公私钥的理解和示例说明
1.生成公钥和私钥 要应用RSA算法,必须先生成公钥和私钥,公钥和私钥的生成可以借助openssl工具.也可以用在线生成公私钥.(网站:http://web.chacuo.net/netrsakeyp ...
- 如何创建自定义的Resource实例
由Resource的构造函数Resources(AssetManager assets, DisplayMetrics metrics, Configuration config)了解到,需要获取ap ...
- 微信小程序的开发框架
wxss:是一套样式语言,用来描述wxml的组件样式:小程序在css基础上做的修改和扩充的版本 css:是一套样式语言,样式表,用来描述xml和html文件样式的呈现: 设备像素:是图片在设备上显示的 ...
- HDU6702 ^&^(思维)
HDU6702 ^&^ 目标为 \((A \oplus C) \& (B \oplus C) = 0\) ,易得: \(A \& B=0\) 时:\(C = 1\) . \(A ...
- nginx配置多个虚拟主机(mac)
1 . 安装 通过homebrew安装nginx,默认安装在:/usr/local/Cellar/nginx/版本号.配置文件在路径:/usr/local/etc/nginx ,默认配置文件ngin ...
- Altium Designer chapter6总结
绘制PCB中需要注意的如下: (1)网络表的载入:网络表是原理图与PCB之间的桥梁,而AD实现了真正的双向同步设计.在装入网表之前需要先添加相应的封装库. (2)元件的布局:一般采用手工布局:按照模块 ...
- 【ABAP系列】SAP ABAP 给初学者-解读function函数的export和import等参数
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 给初学者-解读 ...