【BZOJ】4560: [JLoi2016]字符串覆盖
题解
先用kmp求出来一个ed[i][j]表示在母串的第i位是第j个子串的结尾
考虑状压一个二进制位表示这个子串覆盖过没有
对于最大值,记一个dp[S][i]表示子串的使用状况为S,当前为母串的第i位,最大覆盖的个数
每次枚举S一个没有的子串j,把目标状态记成S^(1 << j - 1) = T
dp[T][i]可以从dp[T][i - 1]取个max过来,如果i还是当前枚举的子串j能匹配上,那么可以从dp[S][i - len[j]] + len[j]转移
然后就是考虑覆盖的情况,有些时候覆盖的情况并不存在,但是这个时候会比答案小,所以一定会被更新的
转移的方式是
dp[T][i] = max(dp[S][k] + i - k)我们使用单调队列来维护dp[S][k] - k即可
对于最小值,由于上面覆盖不存在的情况会比真正的情况要少,我们dp[S][i]的定义改成子串使用状况为S,i这个位置存在一个匹配串的结尾
转移方法同上,只不过需要额外一个数组记录一下S的前缀最小值
最小值的情况还会出现某个子串是另一个子串的子串,这个时候我们删掉被包含在另一个串里的串,将剩余的串作为目标状态取到min值
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
char A[10005];
int N,nxt[10005],len[5],L;
char str[5][1005];
int dp[(1 << 4) + 5][10005],sum[10005],que[10005],ql,qr;
bool ed[10005][5],isalone[5];
void Init() {
scanf("%s",A + 1);
read(N);
for(int i = 1 ; i <= N ; ++i) scanf("%s",str[i] + 1);
L = strlen(A + 1);
memset(ed,0,sizeof(ed));memset(isalone,1,sizeof(isalone));
for(int i = 1 ; i <= N ; ++i) len[i] = strlen(str[i] + 1);
for(int i = 1 ; i <= N ; ++i) {
for(int j = 2 ; j <= len[i] ; ++j) {
int p = nxt[j - 1];
while(p && str[i][p + 1] != str[i][j]) p = nxt[p];
if(str[i][p + 1] == str[i][j]) nxt[j] = p + 1;
else nxt[j] = 0;
}
int p = 0;
for(int k = 1 ; k <= L ; ++k) {
while(p && str[i][p + 1] != A[k]) p = nxt[p];
if(str[i][p + 1] == A[k]) ++p;
else p = 0;
if(p == len[i]) {ed[k][i] = 1;p = nxt[p];}
}
for(int j = 1 ; j <= N ; ++j) {
if(len[i] == len[j]) continue;
p = 0;
for(int k = 1 ; k <= len[j] ; ++k) {
while(p && str[i][p + 1] != str[j][k]) p = nxt[p];
if(str[i][p + 1] == str[j][k]) ++p;
else p = 0;
if(p == len[i]) {isalone[i] = 0;break;}
}
}
}
}
void SolveMax() {
memset(dp,0,sizeof(dp));
for(int S = 0 ; S < (1 << N) ; ++S) {
for(int i = 1 ; i <= N ; ++i) {
if(!(S & (1 << i - 1))) {
que[ql = qr = 1] = 0;
int T = S ^ (1 << i - 1);
for(int k = 1 ; k <= L ; ++k) {
while(ql <= qr && que[ql] <= k - len[i]) ++ql;
while(ql <= qr && dp[S][que[qr]] - que[qr] <= dp[S][k] - k) --qr;
que[++qr] = k;
dp[T][k] = max(dp[T][k - 1],dp[T][k]);
if(ed[k][i]) {
dp[T][k] = max(dp[T][k],dp[S][k - len[i]] + len[i]);
if(ql <= qr) dp[T][k] = max(dp[T][k],dp[S][que[ql]] + k - que[ql]);
}
}
}
}
}
out(dp[(1 << N) - 1][L]);enter;
}
void SolveMin() {
memset(dp,0,sizeof(dp));
for(int S = 0 ; S < (1 << N) ; ++S) for(int k = 0 ; k <= L ; ++k) dp[S][k] = L;
dp[0][0] = 0;
for(int S = 0 ; S < (1 << N) ; ++S) {
for(int i = 1 ; i <= N ; ++i) {
if(!(S & (1 << i - 1))) {
que[ql = qr = 1] = 0;
int T = S ^ (1 << i - 1);
sum[0] = dp[S][0];
for(int k = 1 ; k <= L ; ++k) {
while(ql <= qr && que[ql] <= k - len[i]) ++ql;
while(ql <= qr && dp[S][que[qr]] - que[qr] >= dp[S][k] - k) --qr;
que[++qr] = k;
if(ed[k][i]) {
dp[T][k] = min(dp[T][k],sum[k - len[i]] + len[i]);
if(ql <= qr) dp[T][k] = min(dp[T][k],dp[S][que[ql]] + k - que[ql]);
}
sum[k] = min(sum[k - 1],dp[S][k]);
}
}
}
}
int S = 0;
for(int i = 1 ; i <= N ; ++i) if(isalone[i]) S |= (1 << i - 1);
int ans = L;
for(int k = 1 ; k <= L ; ++k) ans = min(ans,dp[S][k]);
out(ans);space;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int T;
read(T);
while(T--) {Init();SolveMin();SolveMax();}
}
【BZOJ】4560: [JLoi2016]字符串覆盖的更多相关文章
- 【BZOJ4560】[JLoi2016]字符串覆盖 KMP+状压DP
[BZOJ4560][JLoi2016]字符串覆盖 Description 字符串A有N个子串B1,B2,…,Bn.如果将这n个子串分别放在恰好一个它在A中出现的位置上(子串之间可以重叠)这样A中的若 ...
- BZOJ4560 [JLoi2016]字符串覆盖
题意 字符串A有N个子串B1,B2,-,Bn.如果将这n个子串分别放在恰好一个它在A中出现的位置上(子串之间可以重叠) 这样A中的若干字符就被这N个子串覆盖了.问A中能被覆盖字符个数的最小值和最大值. ...
- 并不对劲的bzoj4560:p3269:[JLOI2016]字符串覆盖
题目大意 \(T\)(\(T\leq10\))组询问 每组询问给出一个字符串\(A\)(\(|A|\leq10^4\)),\(n\)(\(n\leq4\))个\(A\)的子串\(B_1,B_2,B_3 ...
- [BZOJ4560][JLOI2016]字符串覆盖(贪心+DP)
先用KMP求出所有可以放的位置,然后两个值分别处理. 最大值: 贪心,4!枚举放的先后位置顺序,2^3枚举相邻两个串是否有交. 若有交,则后一个的起始位置一定是离前一个的结束位置最近的位置,无交也一样 ...
- BZOJ4560 JLOI2016字符串覆盖(kmp+贪心+状压dp+单调队列)
首先kmp求出每个子串能放在哪些位置.接下来的两部分贪心和状压都可以,各取比较方便的. 最大值考虑贪心.考虑枚举子串的左端点出现顺序,在此基础上每个子串的位置肯定都应该尽量靠前,有是否与上个子串有交两 ...
- bzoj 4557: [JLoi2016]侦察守卫 树归
bzoj 4557: [JLoi2016]侦察守卫 设f[x][j]表示覆盖以x为根的子树的所有应该被覆盖的节点,并且以x为根的子树向下j层全部被覆盖的最小代价. 设g[x][j]表示与x距离大于j全 ...
- 笔记:iOS字符串的各种用法(字符串插入、字符串覆盖、字符串截取、分割字符串)(别人的代码直接复制过来的,我脸皮有点厚)
NSString* str=@"hello";//存在代码区,不可变 NSLog(@"%@",str); //1.[字符串插入] NSMutableString ...
- iOS字符串的各种用法(字符串插入、字符串覆盖、字符串截取、分割字符串)
NSString* str=@"hello";//存在代码区,不可变 NSLog(@"%@",str); //1.[字符串插入] NSMutableString ...
- 【BZOJ 3473】 字符串 (后缀数组+RMQ+二分 | 广义SAM)
3473: 字符串 Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串 ...
随机推荐
- oracle 查看临时表空间temp 的使用情况以及扩展表空间
SELECT D.TABLESPACE_NAME,SPACE "SUM_SPACE(M)",BLOCKS SUM_BLOCKS, USED_SPACE )/SPACE*,) &qu ...
- 洛谷 P2376 [USACO09OCT]津贴Allowance 解题报告
P2376 [USACO09OCT]津贴Allowance 题目描述 作为创造产奶纪录的回报,\(Farmer\) \(John\)决定开始每个星期给\(Bessie\)一点零花钱. \(FJ\)有一 ...
- 【CH6201】走廊泼水节
题目大意:给定一棵树,要求增加若干条边,将其转化为完全图,且该完全图以该树为唯一的最小生成树,求增加的边权最小是多少. 题解:完全图的问题一般要考虑组合计数.重新跑一遍克鲁斯卡尔算法,每次并查集在合并 ...
- 缓存面板获取之前页面选中的数据Objuid的方法
String partUid = request.getParameter("contextInstanceUid"); contextInstanceUid是存在总线总的键名,存 ...
- 适用于vue项目的打印插件(转载)
出处:https://www.cnblogs.com/lvyueyang/p/9847813.html // 使用时请尽量在nickTick中调用此方法 //打印 export default (re ...
- bzoj千题计划211:bzoj1996: [Hnoi2010]chorus 合唱队
http://www.lydsy.com/JudgeOnline/problem.php?id=1996 f[i][j][0/1] 表示已经排出队形中的[i,j],最后一个插入的人在[i,j]的i或j ...
- Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) F 构造
http://codeforces.com/contest/967/problem/F 题目大意: 有n个点,n*(n-1)/2条边的无向图,其中有m条路目前开启(即能走),剩下的都是关闭状态 定义: ...
- .NET面试题系列(五)数据结构(Array、List、Queue、Stack)及线程安全问题
常用数据结构的时间复杂度 如何选择数据结构 Array (T[]) 当元素的数量是固定的,并且需要使用下标时. Linked list (LinkedList<T>) 当元素需要能够在列表 ...
- python 喜马拉雅 音乐下载 演示代码
1.主程序文件 import os import json import requests from contextlib import closing from progressbar import ...
- Jquery 较好的效果
仿google图片效果图片展示相册(jquery)的演示页面 产品相册展示插件slideshow多图可翻页 懒人建站 Jquery分享A Jquery分享B Jquery分享C Jquery分享D