Codeforces 822E Liar dp + SA (看题解)
刚开始感觉只要开个dp[ i ][ j ][ 0 / 1 ]表示处理了s的前 i 个用了 k 段, i 是否是最后一段的最后一个字符 的 t串最长匹配长度,
然后wa24, 就gg了。感觉这个转移感觉很对, 但是实际上不对。。。 比如s = ababcde, t = abcde, x = 1, 转移会出现问题。
我们可以用dp[ i ][ j ]表示处理了 s 串的前 i 个, 用了 j 段的最大匹配长度, 我们转移的时候时候肯定是在后面接lcp, 套个sa就好啦。
#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long using namespace std; const int N = 2e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-;
const double PI = acos(-); template<class T> bool chkmax(T& a, T b) {
return a < b ? a = b, true : false;
}
template<class T> bool chkmin(T& a, T b) {
return a > b ? a = b, true : false;
} int Log[N];
struct ST {
int dp[N][], ty;
void build(int n, int b[], int _ty) {
ty = _ty;
for(int i = -(Log[]=-); i < N; i++)
Log[i] = Log[i - ] + ((i & (i - )) == );
for(int i = ; i <= n; i++) dp[i][] = ty * b[i];
for(int j = ; j <= Log[n]; j++)
for(int i = ; i + ( << j) - <= n; i++)
dp[i][j] = max(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
int query(int x, int y) {
int k = Log[y - x + ];
return ty * max(dp[x][k], dp[y - ( << k) + ][k]);
}
}; int r[N], sa[N], _t[N], _t2[N], c[N], rk[N], lcp[N];
void buildSa(int *r, int n, int m) {
int i, j = , k = , *x = _t, *y = _t2;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[i] = r[i]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for(int k = ; k <= n; k <<= ) {
int p = ;
for(i = n - k; i < n; i++) y[p++] = i;
for(i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[y[i]]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = ; x[sa[]] = ;
for(int i = ; i < n; i++) {
if(y[sa[i - ]] == y[sa[i]] && y[sa[i - ] + k] == y[sa[i] + k])
x[sa[i]] = p - ;
else x[sa[i]] = p++;
}
if(p >= n) break;
m = p;
}
for(i = ; i < n; i++) rk[sa[i]] = i;
for(i = ; i < n - ; i++) {
if(k) k--;
j = sa[rk[i] - ];
while(r[i + k] == r[j + k]) k++;
lcp[rk[i]] = k;
}
} int n, m, x, tot, mxc = ;
int dp[N][], B;
char s[N], t[N];
ST rmq; int getLcp(int i, int j) {
i = rk[i];
j = rk[j + n + ];
if(i > j) swap(i, j);
return rmq.query(i + , j);
} int main() {
scanf("%d%s", &n, s);
scanf("%d%s", &m, t);
scanf("%d", &x);
for(int i = ; s[i]; i++) r[tot++] = s[i];
r[tot++] = mxc++;
for(int i = ; t[i]; i++) r[tot++] = t[i];
r[tot] = ;
buildSa(r, tot + , mxc);
rmq.build(tot, lcp, -);
memset(dp, -, sizeof(dp));
dp[][] = ;
int LCP = getLcp(, );
if(LCP) dp[LCP - ][] = LCP;
for(int i = ; i < n - ; i++) {
for(int j = ; j <= x; j++) {
if(~dp[i][j]) {
chkmax(dp[i + ][j], dp[i][j]);
if(j == x) continue;
int LCP = getLcp(i + , dp[i][j]);
if(LCP) chkmax(dp[i + LCP][j + ], dp[i][j] + LCP);
}
}
}
bool flag = false;
for(int i = ; i < n; i++)
for(int j = ; j <= x; j++)
if(dp[i][j] == m) flag = true;
puts(flag ? "YES" : "NO");
return ;
} /*
*/
Codeforces 822E Liar dp + SA (看题解)的更多相关文章
- Codeforces 1017F The Neutral Zone (看题解)
这题一看就筛质数就好啦, 可是这怎么筛啊, 一看题解, 怎么会有这么骚的操作. #include<bits/stdc++.h> #define LL long long #define f ...
- Codeforces 229E Gifts 概率dp (看题解)
Gifts 感觉题解写的就是坨不知道什么东西.. 看得这个题解. #include<bits/stdc++.h> #define LL long long #define LD long ...
- Codeforces 1155F Delivery Oligopoly dp(看题解)
看别人写的才学会的... 我们考虑刚开始的一个点, 然后我们枚举接上去的一条一条链, dp[mask]表示当前已经加进去点的状态是mask所需的最少边数. 反正就是很麻烦的一道题, 让我自己写我是写不 ...
- Codeforces 196E Opening Portals MST (看题解)
Opening Portals 我们先考虑如果所有点都是特殊点, 那么就是对整个图求个MST. 想在如果不是所有点是特殊点的话, 我们能不能也 转换成求MST的问题呢? 相当于我们把特殊点扣出来, 然 ...
- Codeforces 725E Too Much Money (看题解)
Too Much Money 最关键的一点就是这个贪心可以在sqrt(n)级别算出答案. 因为最多有sqrt(n)个不同的数值加入. 我们可以发现最优肯定加入一个. 然后维护一个当前可以取的最大值, ...
- Codeforces 750E New Year and Old Subsequence 线段树 + dp (看题解)
New Year and Old Subsequence 第一感觉是离线之后分治求dp, 但是感觉如果要把左边的dp值和右边的dp值合起来, 感觉很麻烦而且时间复杂度不怎么对.. 然后就gun取看题解 ...
- [LOJ#516]「LibreOJ β Round #2」DP 一般看规律
[LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...
- Codeforces 547C/548E - Mike and Foam 题解
目录 Codeforces 547C/548E - Mike and Foam 题解 前置芝士 - 容斥原理 题意 想法(口胡) 做法 程序 感谢 Codeforces 547C/548E - Mik ...
- Codeforces Round #668 (Div. 2)A-C题解
A. Permutation Forgery 题目:http://codeforces.com/contest/1405/problem/A 题解:这道题初看有点吓人,一开始居然想到要用全排序,没错我 ...
随机推荐
- OpenStack实践系列⑥构建虚拟机实例
OpenStack实践系列⑥构建虚拟机实例 四.创建一台虚拟机图解网络,并创建一个真实的桥接网络 创建一个单一扁平网络(名字:flat),网络类型为flat,网络适共享的(share),网络提供者:p ...
- Callcenter 模块解析
CallCenter模块详细介绍 一. Callcenter模块说明: 提供了呼叫中心的ACD功能,把客户端通过不同的”方案”和”等级”分配给来电,一个以”评分”为基础的系统是用来分配这些呼入.来电者 ...
- POJ 1006 同余方程组
以前的做法 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring& ...
- 前端 ----jQuery的动画效果
03-jQuery动画效果 jQuery提供的一组网页中常见的动画效果,这些动画是标准的.有规律的效果:同时还提供给我们了自定义动画的功能. 显示动画 方式一: $("div" ...
- 关于socket.io获取客户端真实IP地址
1 前言 由于使用了CDN加速,导致了socket.handshake.address拿到值都是服务器的,而没有使用CDN加速时,可以拿到客户端真实IP. 2 代码 if(socket.handsha ...
- iOS9 新功能:Support Universal Links,iOS10 openUrl新函数
先看官方文档:https://developer.apple.com/library/ios/documentation/General/Conceptual/AppSearch/UniversalL ...
- LuoGu P2735 电网 Electric Fences
题目传送门 这个东西,本来我是用求出两条一次函数解析式然后判断在x坐标下的y坐标值来做的 首先因为没考虑钝角三角形,WA了 然后又因为精度处理不好又WA了 一气之下,只能去网上查了查那个皮克定理 首先 ...
- Confluence 6 通过 SSL 或 HTTPS 运行 - 修改你 Confluence 的 server.xml 文件
下一步你需要配置 Confluence 来使用 HTTPS: 编辑 <install-directory>/conf/server.xml 文件. 取消注释下面的行: <Connec ...
- 如何打包/运行jar包,及生成exe文件
关于如何打包/运行jar包,以及生成exe文件.之前各种查询.博客,终于搞明白究竟是咋回事.记得还做过笔记的.今天要打包生成exe用的时候,居然忘了咋怎来着.去查看之前的笔记,死活没找到(好像被删掉了 ...
- MySQL外键使用详解
一.基本概念 1.MySQL中“键”和“索引”的定义相同,所以外键和主键一样也是索引的一种.不同的是MySQL会自动为所有表的主键进行索引,但是外键字段必须由用户进行明确的索引.用于外键关系的字段必须 ...