先用KMP求出所有可以放的位置,然后两个值分别处理。

最大值:

贪心,4!枚举放的先后位置顺序,2^3枚举相邻两个串是否有交。

若有交,则后一个的起始位置一定是离前一个的结束位置最近的位置,无交也一样。

最小值:

首先去掉被其它串包含的串,因为肯定可以和其它串放同样的位置。

将所有串从长到短排序方便DP。

f[S][i]表示当前放的串的情况为S,串目前所覆盖到的最后一个位置为i,覆盖的最小总长度是多少,则有:

当最后一个覆盖到i的串位置与其它串不相交时:f[S][i]=min{f[S'][k]}  这个用一个前缀和优化即可。

当相交时:f[S][i]=min(f[S'][j]+i-j) 因为串已经从长到短排好序了所有没有问题。这个用单调队列优化即可。

写的龟速,跑得飞快。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define mem(a) memset(a,0,sizeof(a))
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=;
char s[][N],A[N];
bool b[],fl[][N];
int T,n,len,L[],pos[][N],num[],nxt[N],p[],st[],ed[],f[][N],g[][N],q[][N]; void KMP(char S[],char T[],int pos[],int &num,bool fl[]){
int n=strlen(T+),m=strlen(S+),j=; nxt[]=;
rep(i,,m){
while (j && S[j+]!=S[i]) j=nxt[j];
if (S[j+]==S[i]) nxt[i]=++j; else nxt[i]=;
}
j=; num=;
rep(i,,n){
while (j && S[j+]!=T[i]) j=nxt[j];
if (S[j+]==T[i]) j++;
if (j==m) pos[++num]=i-m+,fl[i]=,j=nxt[j];
}
} bool chk(char S[],char T[]){
int n=strlen(T+),m=strlen(S+);
rep(i,,n-m+){
bool flag=;
rep(j,,m) if (S[j]!=T[i+j-]){ flag=; break; }
if (!flag) return ;
}
return ;
} void solve_max(){
rep(i,,n) p[i]=i; int ans=; mem(fl);
do{
for (int S=; S<<<(n-); S++){
int x=pos[p[]][]+L[p[]]-,res=L[p[]]; ans=max(ans,res); bool flag=;
rep(i,,n){
int d=upper_bound(pos[p[i]]+,pos[p[i]]+num[p[i]]+,x)-pos[p[i]];
if (S&(<<(i-))){
if (d<=num[p[i]] && pos[p[i]][d]>x) res+=L[p[i]],x=pos[p[i]][d]+L[p[i]]-;
else{ flag=; break; }
}else{
d--;
if (d && pos[p[i]][d]<=x) res+=L[p[i]]-(x-pos[p[i]][d]+),x=pos[p[i]][d]+L[p[i]]-;
else{ flag=; break; }
}
if (!flag) ans=max(ans,res);
}
}
}while (next_permutation(p+,p+n+));
printf("%d\n",ans);
} void solve_min(){
int S0=(<<n)-;
rep(i,,n-) rep(j,i+,n) if (!b[j] && chk(s[j],s[i])) b[j]=,S0^=<<(j-);
memset(f,0x3f,sizeof(f)); memset(g,0x3f,sizeof(g));
mem(f[]); mem(g[]);
rep(i,,(<<n)-) st[i]=,ed[i]=;
rep(i,,len){
for (int S=; S<<<n; S++){
if (S&(S^S0)) continue; g[S][i]=g[S][i-];
rep(j,,n) if (S&(<<(j-)) && fl[j][i]){
int S1=S^(<<(j-));
if (i-L[j]>=) f[S][i]=min(f[S][i],g[S1][i-L[j]]+L[j]);
while (st[S1]<=ed[S1] && q[S1][st[S1]]<=i-L[j]) st[S1]++;
if (st[S1]<=ed[S1]) f[S][i]=min(f[S][i],f[S1][q[S1][st[S1]]]+i-q[S1][st[S1]]);
while (st[S]<=ed[S] && f[S][q[S][ed[S]]]-q[S][ed[S]]>=f[S][i]-i) ed[S]--;
q[S][++ed[S]]=i; g[S][i]=min(g[S][i-],f[S][i]);
}
}
}
printf("%d ",g[S0][len]);
} int main(){
freopen("bzoj4560.in","r",stdin);
freopen("bzoj4560.out","w",stdout);
for (scanf("%d",&T); T--; ){
mem(fl); mem(b); scanf("%s",A+); len=strlen(A+); scanf("%d",&n);
rep(i,,n) scanf("%s",s[i]+),L[i]=strlen(s[i]+);
rep(i,,n-) rep(j,i+,n) if (L[i]<L[j]) swap(s[i],s[j]),swap(L[i],L[j]);
rep(i,,n) KMP(s[i],A,pos[i],num[i],fl[i]);
solve_min(); solve_max();
}
return ;
}

[BZOJ4560][JLOI2016]字符串覆盖(贪心+DP)的更多相关文章

  1. BZOJ4560 JLOI2016字符串覆盖(kmp+贪心+状压dp+单调队列)

    首先kmp求出每个子串能放在哪些位置.接下来的两部分贪心和状压都可以,各取比较方便的. 最大值考虑贪心.考虑枚举子串的左端点出现顺序,在此基础上每个子串的位置肯定都应该尽量靠前,有是否与上个子串有交两 ...

  2. BZOJ4560 [JLoi2016]字符串覆盖

    题意 字符串A有N个子串B1,B2,-,Bn.如果将这n个子串分别放在恰好一个它在A中出现的位置上(子串之间可以重叠) 这样A中的若干字符就被这N个子串覆盖了.问A中能被覆盖字符个数的最小值和最大值. ...

  3. 【BZOJ4560】[JLoi2016]字符串覆盖 KMP+状压DP

    [BZOJ4560][JLoi2016]字符串覆盖 Description 字符串A有N个子串B1,B2,…,Bn.如果将这n个子串分别放在恰好一个它在A中出现的位置上(子串之间可以重叠)这样A中的若 ...

  4. 并不对劲的bzoj4560:p3269:[JLOI2016]字符串覆盖

    题目大意 \(T\)(\(T\leq10\))组询问 每组询问给出一个字符串\(A\)(\(|A|\leq10^4\)),\(n\)(\(n\leq4\))个\(A\)的子串\(B_1,B_2,B_3 ...

  5. 【BZOJ】4560: [JLoi2016]字符串覆盖

    题解 先用kmp求出来一个ed[i][j]表示在母串的第i位是第j个子串的结尾 考虑状压一个二进制位表示这个子串覆盖过没有 对于最大值,记一个dp[S][i]表示子串的使用状况为S,当前为母串的第i位 ...

  6. 字符串处理/贪心 Codeforces Round #307 (Div. 2) B. ZgukistringZ

    题目传送门 /* 题意:任意排列第一个字符串,使得有最多的不覆盖a/b字符串出现 字符串处理/贪心:暴力找到最大能不覆盖的a字符串,然后在b字符串中动态得出最优解 恶心死我了,我最初想输出最多的a,再 ...

  7. 【BZOJ-3174】拯救小矮人 贪心 + DP

    3174: [Tjoi2013]拯救小矮人 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 686  Solved: 357[Submit][Status ...

  8. BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP

    BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...

  9. 洛谷P4823 拯救小矮人 [TJOI2013] 贪心+dp

    正解:贪心+dp 解题报告: 传送门! 我以前好像碰到过这题的说,,,有可能是做过类似的题qwq? 首先考虑这种显然是dp?就f[i][j]:决策到了地i个人,跑了j个的最大高度,不断更新j的上限就得 ...

随机推荐

  1. composer 上提交自己的包

    先在github上复制自己的地址在 https://packagist.org/packages/submit ->check->submit

  2. 谈一谈我所了解的https

    一. http协议 首先我并不会很深入的去探讨这个东西,即使我曾经花了很长的时间去研究这个东西.主要是我考虑到1. 自己没有系统的去学习这一块的知识,讲解的会比较的肤浅.2. 就算是懂这个东西也不一定 ...

  3. 树的直径(两个bfs)

    题目链接:https://cn.vjudge.net/problem/POJ-2631 树的直径:树中的最长链 具体思路:随便找一个点bfs,然后找到最长的链,然后再以找到的点作为起点进行bfs,然后 ...

  4. django框架<三>

    一.ORM操作  1.django orm创建数据库的方法 (1)指定连接pymysql(python3.x),先配置__init__.py import pymysql pymysql.instal ...

  5. shell将多行文本重定向到文件【转】

    在shell中,使用Here Document方式将文本重定向到文件,格式如下: ( cat << EOF 要写的文本 EOF ) > 目标文件 示例test.sh: #! /bin ...

  6. 55.Jump Game---dp

    题目链接 题目大意:给一个数组,第i个位置的值表示当前可以往前走的最远距离,求从第一个位置能否顺利走到最后一个位置.例子如下: 法一(借鉴):DP,dp[i]表示从上一个位置走到当前位置时,剩余的可以 ...

  7. Deep Learning基础--word2vec 中的数学原理详解

    word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了很多人的关注.由于 word2vec 的作者 Tomas Miko ...

  8. Denoise Autoencoder简单理解

    自编码器通过学习隐含特征来表达原始数据,那什么是denoise autoencoder呢? 关于Autoencoder参考:http://blog.csdn.net/on2way/article/de ...

  9. ~Delphi const 杂谈~

    来自:http://www.cnblogs.com/tibetwolf/articles/1785744.html ------------------------------------------ ...

  10. admin组件详解

    admin组件详解 先根据admin组件启动流程复习下django项目启动至请求过来发生的事 1将admin组件注册进app 2django项目启动 3在运行到定制的admin时执行其下面的apps文 ...