Liar

刚开始感觉只要开个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 (看题解)的更多相关文章

  1. Codeforces 1017F The Neutral Zone (看题解)

    这题一看就筛质数就好啦, 可是这怎么筛啊, 一看题解, 怎么会有这么骚的操作. #include<bits/stdc++.h> #define LL long long #define f ...

  2. Codeforces 229E Gifts 概率dp (看题解)

    Gifts 感觉题解写的就是坨不知道什么东西.. 看得这个题解. #include<bits/stdc++.h> #define LL long long #define LD long ...

  3. Codeforces 1155F Delivery Oligopoly dp(看题解)

    看别人写的才学会的... 我们考虑刚开始的一个点, 然后我们枚举接上去的一条一条链, dp[mask]表示当前已经加进去点的状态是mask所需的最少边数. 反正就是很麻烦的一道题, 让我自己写我是写不 ...

  4. Codeforces 196E Opening Portals MST (看题解)

    Opening Portals 我们先考虑如果所有点都是特殊点, 那么就是对整个图求个MST. 想在如果不是所有点是特殊点的话, 我们能不能也 转换成求MST的问题呢? 相当于我们把特殊点扣出来, 然 ...

  5. Codeforces 725E Too Much Money (看题解)

    Too Much Money 最关键的一点就是这个贪心可以在sqrt(n)级别算出答案. 因为最多有sqrt(n)个不同的数值加入. 我们可以发现最优肯定加入一个. 然后维护一个当前可以取的最大值, ...

  6. Codeforces 750E New Year and Old Subsequence 线段树 + dp (看题解)

    New Year and Old Subsequence 第一感觉是离线之后分治求dp, 但是感觉如果要把左边的dp值和右边的dp值合起来, 感觉很麻烦而且时间复杂度不怎么对.. 然后就gun取看题解 ...

  7. [LOJ#516]「LibreOJ β Round #2」DP 一般看规律

    [LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...

  8. Codeforces 547C/548E - Mike and Foam 题解

    目录 Codeforces 547C/548E - Mike and Foam 题解 前置芝士 - 容斥原理 题意 想法(口胡) 做法 程序 感谢 Codeforces 547C/548E - Mik ...

  9. Codeforces Round #668 (Div. 2)A-C题解

    A. Permutation Forgery 题目:http://codeforces.com/contest/1405/problem/A 题解:这道题初看有点吓人,一开始居然想到要用全排序,没错我 ...

随机推荐

  1. 通过python操作smtplib模块发送邮件

    # gconf.py SMTP_SERVER_HOST='smtp.exmail.qq.com' SMTP_SERVER_PORT=25 SMTP_USER='jack@qq.com' # 邮箱客户端 ...

  2. hue的历史查询记录querys乱码问题解决

    hue的历史查询记录querys乱码问题解决: master1中配置文件/home/hadoop/.versions/hue-3.10.0/desktop/conf/hue.ini 可以看到连接的是m ...

  3. Zabbix3.0.4监控Windows的CPU使用百分比并在CPU使用率超过90%触发报警

    Zabbix3.0.4监控Windows的CPU使用百分比 Zabbix 自带的模块没有 CPU 使用率(百分比)这个监控项,我们可以通过添加计数器的方式实现 CPU 百分比的监控. 1.在Zabbi ...

  4. linux无法启动httpd服务问题

    httpd 服务启动报错,可能出现的问题比较多,通过查看日志看是什么报错 (tail  200f /etc/httpd/logs/error_log) 1.查看防火墙是不是关闭状态 2.查看80端口是 ...

  5. JS:判断是否是移动端

    通过User-Agent判断 代码: if(navigator.userAgent.match(/mobile/i)) { //业务层代码 $('body').removeClass("si ...

  6. 51nod--1240莫比乌斯函数 (数论)

    题目: 1240 莫比乌斯函数 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 莫比乌斯函数,由德国数学家和天文学家莫比乌斯提出.梅滕斯(Mertens)首先 ...

  7. windows IDEA注册码激活方法(2018.4.8)靠谱可用!

    简介 intellij idea 2018注册码是针对intellij idea 2018软件研发推出,它的使用需要和激活补丁一起使用,安装包里面也拥有破解补丁, 所有无需在进行单独的下载:不过如果选 ...

  8. mysql定时任务,每天的零点执行一个存储过程

    1 前言 利用navicat工具来写存储过程及定时执行,此文章是按照自身经验总结的,仅作为记录使用. 2 步骤 2.1 新建过程 2.2 在函数体写你需要执行的代码 CREATE DEFINER=`r ...

  9. python PIL实现图片合成

    在项目中需要将两张图片合在一起.遇到两种情况,一种就是两张非透明图片的合成, 一种是涉及到透明png的合成. 相关API见 http://pillow.readthedocs.io/en/latest ...

  10. mysql修改表、字段、库的字符集(转)

    原文链接:http://fatkun.com/2011/05/mysql-alter-charset.html MySQL中默认字符集的设置有四级:服务器级,数据库级,表级 .最终是字段级 的字符集设 ...