[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}\)都有 \[ ...
随机推荐
- js点击获取—通过JS获取图片的绝对对坐标位置
一.通过JS获取鼠标点击时图片的相对坐标位置 源代码如下所示: <!DOCTYPE html> <html lang="en"> <head> ...
- selenium 浏览器无界面模式运行
以Chrome浏览器为例: 方法一: from selenium.webdriver import Chrome, ChromeOptions opt = ChromeOptions() # 创建Ch ...
- 20180813-Java 重写(Override)与重载(Overload)
Java 重写(Override)与重载(Overload) class Animal{ public void move(){ System.out.println("动物可以移动&quo ...
- ubuntu18.04英文环境解决各种软件中文乱码问题
如果要同时支持中文也支持英文,进入到该软件的字体设置界面,字体格式选择为: Noto Sans CJK SC
- 生产环境下,oracle不同用户间的数据迁移。第一部分
:任务名称:生产环境下schema ELON数据迁移至schema TIAN ######################################## 测试一:测试参数 数据泵数据导出:exp ...
- MySQL 安装示例数据库(employee、world、sakila、menagerie 等)
sakila 示例数据库官方资料及安装说明,注意查看示例数据库支持的版本是否匹配你的数据库. 为了测试,有时候需要大量的数据集,MySQL 官方提供了用于测试的示例数据库,下载页面在 这里. 下面以 ...
- WPF样式统一之DevExpress设置窗体,控件为Office风格
DevExpress相信不少人用过,虽然人家不是免费的,但是用过的应该都知道,确实是花了心血的C#插件,下面来介绍下在DevExpress下如何统一设置自己的WPF程序为经典Windows风格. 窗体 ...
- HTML--JS 获取选择框信息
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- hihoCoder 1014 : Trie树(字典树)
传送门 Description 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小 ...
- Lambda -语法使用,代码简化
使用Lambda的方式实现线程 线程中()是run方法的(),可用来接受参数,格式: new Thread(()->{ System.out.println(Thread.currentThre ...