Codeforces Round #422 (Div. 2) E. Liar 贪心 dp 后缀数组
来源:互联网 发布:快递员扫码发短信软件 编辑:程序博客网 时间:2024/06/08 16:25
给两个串,a与b,长度1e5,最多可以在a中选出x段互不相交的连续子串,问能不能拼成b,x的范围最多为30。
解法:
可以想到dp,dp[i][j]表示 a 串前 j 个字符取 i 段,能匹配到 b 串的最大前缀。这个状态是通过贪心构造的。
转移的时候也是贪心转移,分为多一段和不要这个字符两种情况。
a) 多一段:dp[i+1][j+lcp(a[j],b[dp[i][j]])]=max(dp[i+1][j+lcp(a[j],b[dp[i][j]])],dp[i][j]+lcp(a[j],dp[i][j])); 因为如果要从a串的a[j]处, b串的b[dp[i][j]]处取一段相同子串,可以贪心地取最长的一段,其中lcp(a[j],dp[i][j]) 可以拿后缀数组或者哈希维护。
b) 不要当前字符:dp[i][j+1]=max(dp[i][j+1],dp[i][j]);
#include <bits/stdc++.h>using namespace std;const int maxn=200005;string s,t,o;bool flag;int N,K,Rank[maxn],tmp[maxn],sa[maxn],lcp[maxn],n,m,x,st[20][maxn],dp[32][maxn];inline bool compare_sa(int i,int j) { if (Rank[i]!=Rank[j]) return Rank[i]<Rank[j]; else { int ri=(i+K<=N)?Rank[i+K]:-1; int rj=(j+K<=N)?Rank[j+K]:-1; return ri<rj; }}inline void construct_sa(string S,int *sa) { N=S.length(); for (int i=0;i<=N;++i) { sa[i]=i; Rank[i]=i<N?S[i]:-1; } for (K=1;K<=N;K*=2) { sort(sa,sa+N+1,compare_sa); tmp[sa[0]]=0; for (int i=1;i<=N;++i) tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0); for (int i=0;i<=N;++i) Rank[i]=tmp[i]; }}inline void construct_lcp(string S,int *sa,int *lcp) { N=S.length(); int h=0; lcp[0]=0; for (int i=0;i<N;++i) { int j=sa[Rank[i]-1]; h=max(h-1,0); for (;j+h<N&&i+h<N;++h) if (S[j+h]!=S[i+h]) break; lcp[Rank[i]-1]=h; }}inline void construct_rmq(int *lcp,int n) { for (int i=0;i<n;++i) st[0][i]=lcp[i]; for (int i=1;i<20;++i) for (int j=0;j+(1<<i)-1<n;++j) st[i][j]=min(st[i-1][j],st[i-1][j+(1<<(i-1))]);}inline int query_rmq(int i,int j) { int x=0; while ((1<<(x+1))<=j-i+1) ++x; return min(st[x][i],st[x][j-(1<<x)+1]);}void solve() { for (int i=0;i<=x;++i) for (int j=0;j<=n;++j) { if (dp[i][j]>=m) { puts("YES"); return; } int _lcp=query_rmq(min(Rank[j],Rank[dp[i][j]+n+1]),max(Rank[j],Rank[dp[i][j]+n+1])-1); dp[i+1][j+_lcp]=max(dp[i+1][j+_lcp],dp[i][j]+_lcp); dp[i][j+1]=max(dp[i][j+1],dp[i][j]); } puts("NO");}int main(){ cin>>n>>s>>m>>t>>x; o=s+'$'+t; construct_sa(o,sa); construct_lcp(o,sa,lcp); construct_rmq(lcp,o.length()+1); solve(); return 0;}
阅读全文
1 0
- Codeforces Round #422 (Div. 2) E. Liar 贪心 dp 后缀数组
- Codeforces Round #353 (Div. 2) E. Trains and Statistic dp 贪心,DP,线段树
- dp+Codeforces Round #274 (Div. 2)E
- 【DP】Codeforces Round #341 (Div. 2) E
- Codeforces Round #316 (Div. 2) E dp
- Codeforces Round #371 (Div. 2) E dp
- Codeforces Round #376 (Div. 2) E dp
- Codeforces Round #288 (Div. 2) E. Arthur and Brackets 贪心 区间dp
- Codeforces Round #227 (Div. 2)---E. George and Cards(贪心, 树状数组+set维护, 好题!)
- Codeforces Round #262 (Div. 2)E(贪心+暴搜)
- Codeforces Round #364 (Div. 2) E. Connecting Universities 贪心 + dfs
- Codeforces Round #401 (Div. 2) E. Hanoi Factory 贪心+栈
- Codeforces Round #401(Div. 2)E. Hanoi Factory【贪心+栈】
- Codeforces Round #401 (Div. 2) E. Hanoi Factory 贪心+栈
- Codeforces Round #360 (Div. 2) E. The Values You Can Make dp ,滚动数组
- 【codeforces】Codeforces Round #305 (Div. 1)E. Mike and Friends【后缀数组+线段树】
- E. Vladik and cards Codeforces Round #384 (Div. 2) 好题 二分+(贪心+状态压缩DP)判断
- Codeforces Round #261 (Div. 2) E. Pashmak and Graph【DP】
- Luogu P1328 [NOIP2014]生活大爆炸版石头剪刀布
- 金山&Q管win10 锁定Edge算法分析
- linux 创建连接命令 ln -s 软链接
- OpenGL 02 OpenGL缓存数据
- 2.Android硬件访问服务编写系统代码
- Codeforces Round #422 (Div. 2) E. Liar 贪心 dp 后缀数组
- tomcat添加为linux服务
- hdu5306 Gorgeous Sequence(线段树:复杂区间更新)
- mysql创建远程用户并授权
- SQL学习
- 什么是数据库,什么是SQL,什么是MySQL
- Spring-Bean的作用域
- C#学习过程中vs使用和代码编辑技巧总结
- HAUToj 1284: SP教数学 (线段树+矩阵快速幂