Codeforces Round #422 (Div. 2) E. Liar 后缀数组+RMQ+DP
The first semester ended. You know, after the end of the first semester the holidays begin. On holidays Noora decided to return to Vičkopolis. As a modest souvenir for Leha, she brought a sausage of length m from Pavlopolis. Everyone knows that any sausage can be represented as a string of lowercase English letters, the length of which is equal to the length of the sausage.
Leha was very pleased with the gift and immediately ate the sausage. But then he realized that it was a quite tactless act, because the sausage was a souvenir! So the hacker immediately went to the butcher shop. Unfortunately, there was only another sausage of length nin the shop. However Leha was not upset and bought this sausage. After coming home, he decided to cut the purchased sausage into several pieces and number the pieces starting from 1 from left to right. Then he wants to select several pieces and glue them together so that the obtained sausage is equal to the sausage that Noora gave. But the hacker can glue two pieces together only when the number of the left piece is less than the number of the right piece. Besides he knows that if he glues more than x pieces, Noora will notice that he has falsified souvenir sausage and will be very upset. Of course Leha doesn’t want to upset the girl. The hacker asks you to find out whether he is able to cut the sausage he bought, and then glue some of the pieces so that Noora doesn't notice anything.
Formally, you are given two strings s and t. The length of the string s is n, the length of the string t is m. It is required to select several pairwise non-intersecting substrings from s, so that their concatenation in the same order as these substrings appear in s, is equal to the string t. Denote by f(s, t) the minimal number of substrings to be chosen so that their concatenation is equal to the string t. If it is impossible to choose such substrings, then f(s, t) = ∞. Leha really wants to know whether it’s true that f(s, t) ≤ x.
The first line contains single integer n (1 ≤ n ≤ 105) — length of sausage bought by Leha, i.e. the length of the string s.
The second line contains string s of the length n consisting of lowercase English letters.
The third line contains single integer m (1 ≤ m ≤ n) — length of sausage bought by Noora, i.e. the length of the string t.
The fourth line contains string t of the length m consisting of lowercase English letters.
The fifth line contains single integer x (1 ≤ x ≤ 30) — the maximum number of pieces of sausage that Leha can glue so that Noora doesn’t notice anything.
In the only line print "YES" (without quotes), if Leha is able to succeed in creating new sausage so that Noora doesn't notice anything. Otherwise print "NO" (without quotes).
9
hloyaygrt
6
loyyrt
3
YES
Let's consider the first sample.
In the optimal answer, Leha should cut the sausage he bought in the following way: hloyaygrt = h + loy + a + y + g + rt. Then he numbers received parts from 1 to 6:
- h — number 1
- loy — number 2
- a — number 3
- y — number 4
- g — number 5
- rt — number 6
Hereupon the hacker should glue the parts with numbers 2, 4 and 6 and get sausage loyygrt equal to one that is given by Noora. Thus, he will have to glue three pieces. Since x = 3 you should print "YES" (without quotes).
In the second sample both sausages coincide with sausages from the first sample. However since x = 2 you should print "NO" (without quotes).
题意:
给你两个字符串,S,T
你可以将S分成任意块编号,至多选出X块编号递增的顺序组成新的串
问你是否能组成T串
题解:
很久没做后缀数组的题了,回顾了下
设定dp[i][j],表示 0~(i-1)之前 挑选了j块 到达的最大位置
那么对于S串的 i 位置,和T串的dp[i][j] + 1这个位置开始,最长公共前缀是多少?
假设为t , 那么转移就是 dp[i + t][j+1] = max(dp[i + t][j+1] , dp[i][j] + t);
我们用后缀数组预处理出来lcp,那么查询的时候直接利用RMQ的O(1) 查询就好了
整体复杂度O(nlogn + n*30)
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 5e5+, M = 1e3+,inf = 2e9+; int *ran,r[N],sa[N],height[N],wa[N],wb[N],wm[N];
bool cmp(int *r,int a,int b,int l) {
return r[a] == r[b] && r[a+l] == r[b+l];
}
void SA(int *r,int *sa,int n,int m) {
int *x=wa,*y=wb,*t;
for(int i=;i<m;++i)wm[i]=;
for(int i=;i<n;++i)wm[x[i]=r[i]]++;
for(int i=;i<m;++i)wm[i]+=wm[i-];
for(int i=n-;i>=;--i)sa[--wm[x[i]]]=i;
for(int i=,j=,p=;p<n;j=j*,m=p){
for(p=,i=n-j;i<n;++i)y[p++]=i;
for(i=;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
for(i=;i<m;++i)wm[i]=;
for(i=;i<n;++i)wm[x[y[i]]]++;
for(i=;i<m;++i)wm[i]+=wm[i-];
for(i=n-;i>=;--i)sa[--wm[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,i=p=,x[sa[]]=;i<n;++i) {
x[sa[i]]=cmp(y,sa[i],sa[i-],j)?p-:p++;
}
}
ran=x;
}
void Height(int *r,int *sa,int n) {
for(int i=,j=,k=;i<n;height[ran[i++]]=k)
for(k?--k:,j=sa[ran[i]-];r[i+k] == r[j+k];++k);
}
int dp[N][];
int n,m,f[N][];
char s[N],t[N];
void Lcp_init() {
for(int i = ; i <= n+m+; ++i)
dp[i][] = height[i];
for(int j = ; (<<j) <= n + m + ; ++j) {
for(int i = ; i + (<<j) - <= n+m-; ++i) {
dp[i][j] = min(dp[i][j-],dp[i+(<<(j-))][j-]);
}
}
}
int lcp(int l,int r) {
l = ran[l], r = ran[r];
if(l > r) swap(l,r);
++l;
int len = r - l + ;
int k = ;
while((<<(k+)) <= len) ++k;
return min(dp[l][k], dp[r - (<<k) + ][k]);
}
int main() {
scanf("%d%s%d%s",&n,s,&m,t);
for(int i = ; i < n; ++i) r[i] = s[i] - 'a' + ;
r[n] = '*';
for(int i = n+; i < m+n+; ++i) r[i] = t[i - n - ] - 'a' + ;
r[n+m+] = ;
SA(r,sa,n+m++,);
Height(r,sa,n+m+);
Lcp_init();
int X;
scanf("%d",&X);
int mx = ;
for(int i = ; i <= n; ++i) {
for(int j = ; j <= X; ++j) {
f[i+][j] = max(f[i+][j],f[i][j]);
int t = lcp(i,f[i][j] + n + );
f[i + t][j+] = max(f[i + t][j+] , f[i][j] + t);
mx = max(f[i][j],mx);
}
}
if(mx == m) puts("YES");
else puts("NO");
return ;
}
Codeforces Round #422 (Div. 2) E. Liar 后缀数组+RMQ+DP的更多相关文章
- Codeforces Round #422 (Div. 2)E. Liar sa+st表+dp
题意:给你两个串s,p,问你把s分开顺序不变,能不能用最多k段合成p. 题解:dp[i][j]表示s到了前i项,用了j段的最多能合成p的前缀是哪里,那么转移就是两种,\(dp[i+1][j]=dp[i ...
- Codeforces Round #422 (Div. 2)
Codeforces Round #422 (Div. 2) Table of Contents Codeforces Round #422 (Div. 2)Problem A. I'm bored ...
- Codeforces Round #244 (Div. 2)D (后缀自己主动机)
Codeforces Round #244 (Div. 2)D (后缀自己主动机) (标号为0的节点一定是null节点,不管怎样都不能拿来用,切记切记,以后不能再错了) 这题用后缀自己主动机的话,对后 ...
- Codeforces Round #267 (Div. 2) C. George and Job(DP)补题
Codeforces Round #267 (Div. 2) C. George and Job题目链接请点击~ The new ITone 6 has been released recently ...
- Codeforces Round #364 (Div. 1) (差一个后缀自动机)
B. Connecting Universities 大意: 给定树, 给定2*k个点, 求将2*k个点两两匹配, 每个匹配的贡献为两点的距离, 求贡献最大值 单独考虑每条边$(u,v)$的贡献即可, ...
- 【Codeforces Round #422 (Div. 2) D】My pretty girl Noora
[题目链接]:http://codeforces.com/contest/822/problem/D [题意] 有n个人参加选美比赛; 要求把这n个人分成若干个相同大小的组; 每个组内的人数是相同的; ...
- 【Codeforces Round #422 (Div. 2) C】Hacker, pack your bags!(二分写法)
[题目链接]:http://codeforces.com/contest/822/problem/C [题意] 有n个旅行计划, 每个旅行计划以开始日期li,结束日期ri,以及花费金钱costi描述; ...
- 【Codeforces Round #422 (Div. 2) B】Crossword solving
[题目链接]:http://codeforces.com/contest/822/problem/B [题意] 让你用s去匹配t,问你最少需要修改s中的多少个字符; 才能在t中匹配到s; [题解] O ...
- 【Codeforces Round #422 (Div. 2) A】I'm bored with life
[题目链接]:http://codeforces.com/contest/822/problem/A [题意] 让你求a!和b!的gcd min(a,b)<=12 [题解] 哪个小就输出那个数的 ...
随机推荐
- [uiautomator篇] UiWatcher的使用
//package com.softwinner.pad.mark3d; package com.softwinner.performance.benchmark.mark3d; import and ...
- MHA脚本master_ip_failover.pl(三)
#!/usr/bin/env perl use strict;use warnings FATAL => 'all'; use Getopt::Long; my ( $command, $ssh ...
- [UOJ#221][BZOJ4652][Noi2016]循环之美
[UOJ#221][BZOJ4652][Noi2016]循环之美 试题描述 牛牛是一个热爱算法设计的高中生.在他设计的算法中,常常会使用带小数的数进行计算.牛牛认为,如果在 k 进制下,一个数的小数部 ...
- [UOJ#219][BZOJ4650][Noi2016]优秀的拆分
[UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...
- [luoguP1131] [ZJOI2007]时态同步(贪心)
传送门 显然是一棵树. 又显然一段一段地增加比较优. 我们可以dfs,并且尽量把每一个节点所有子树中所有节点的时间增加到一样. #include <vector> #include < ...
- 【bzoj2115】[Wc2011] Xor【高斯消元】
题目大意:给出一个无向有权图,找出一条从1到n的路径,使得路径上权值的异或和最大,路径可以重复走 Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条 ...
- tarkjan求无向图割点模板
#include<bits/stdc++.h> using namespace std; typedef long long ll; int n,m; ; ; struct node { ...
- *Codeforces963C. Cutting Rectangle
$n \leq 200000$种互不相同的矩形,给长宽和数量,都$\leq 1e12$,问有多少种大矩形只沿平行长和宽切正好切成这些矩形. 首先可以发现在一个合法情况下,有些矩形的位置是可以乱挪的,比 ...
- Bootstrap开启模态框后对数据处理(标记模态框的开启与关闭状态)
JS用全局变量标记状态,方法中动态修改全局变量以标记状态是一个重要思想. 需求:组合条件查询数据,查询完之后填充到模态框中,开启模态框,模态框中有组合条件查询,此时查询只需要更新模态框表格数据不需要开 ...
- Yii 之视图布局
控制器代码: //设置的布局文件 public $layout = 'common'; public function actionAbout(){ $data = array('page_name' ...