题目链接:bzoj2121
题目大意:
BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删除,如果删除,则将删除后L分裂成的左右两部分合并。举个例子,L=’abcdefg’ , S={‘de’},如果BX选择将’de’从L中删去,则删后的L=’abcfg’。现在BX可以进行任意多次操作(删的次数,顺序都随意),他想知道最后L串的最短长度是多少。

对于100%数据,满足|L|<151,|S|<31|L|,SS中的每个元素|p|<21|p|

题解:
区间dp
这题好强啊。。【看到范围这么小的题我都害怕
分成两段dp

设f[i][j][k][l]f[i][j][k][l]表示在字符串LL中的区间ii~jj能否删剩第kk个串的前ll个,ok[i][j]ok[i][j]表示字符串LL中ii~jj这一段能否被删光(这里的两个都是bool类型的数组)
那么有:(s是原串L,str是字符串集合
f[i][j][k][l]=(s[j]f[i][j][k][l]= (s[j]==str[k][l]str[k][l] && f[i][j−1][k][l−1])f[i][j-1][k][l-1])
枚举i≤mid<j
f[i][j][k][l]=(f[i][mid][k][l]f[i][j][k][l] = (f[i][mid][k][l] && ok[mid+1][j])ok[mid+1][j])
同时更新ok:ok[i][j]|=f[i][j][k][len[k]]ok[i][j]|=f[i][j][k][len[k]]

设ans[i]表示前i个能被删成的最短长度
1. ans[i]=ans[i-1]+1
2. 枚举断点1≤j≤i,若ok[j][i]==true,那么有ans[i]=min(ans[i],ans[j-1])

说说优化(对第一段dp的
观察可以发现,第一维i是没有用的啊。于是减一维,每次循环清一下空。
然后看范围,最后一维l最大也只有21啊,状压一下。
于是f[i][j][k]f[i][j][k](假设没删第一维..好讲一点..)就表示i~j能删剩第k个串的哪几个,若第l位(二进制下)为1即能删剩第k个串的第l位。
转移的话相应改改就好了。

如果多预处理一个数组p[i][j]表示LL中的第i位能与第j个小串的那些位匹配,即若p[i][j]的第k位(二进制)为1,就说明s[i]s[i]=str[j][k]str[j][k]的话,会快一点。
没有用p数组的:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 200
#define M 40int bit[M],f[N][M],len[M],ans[N];
char s[N],str[M][M];bool ok[N][N];
int mymin(int x,int y){return (x<y)?x:y;}
int main()
{int n,m,i,j,k,l;gets(s+1);n=strlen(s+1);scanf("%d\n",&m);for (i=1;i<=m;i++) {scanf("%s",str[i]+1);len[i]=strlen(str[i]+1);}bit[0]=1;for (i=1;i<=21;i++) bit[i]=bit[i-1]<<1;memset(ok,false,sizeof(ok));for (i=n;i>=1;i--)
    {        memset(f,0,sizeof(f));
        for (j=i;j<=n;j++)
        {            if (i==j)
            {                for (k=1;k<=m;k++)
                {                    if (s[j]==str[k][1]) f[j][k]=1;
                    if (f[j][k]&bit[len[k]-1]) ok[i][j]=true;
                }continue;
            }
            for (k=1;k<=m;k++)
            {                for (l=2;l<=len[k];l++)
                  if (s[j]==str[k][l] && f[j-1][k]&bit[l-2]) f[j][k]|=bit[l-1];
                for (l=i;l<j;l++)
                 if (ok[l+1][j]) f[j][k]|=f[l][k];
                if (f[j][k]&bit[len[k]-1]) ok[i][j]=true;
            }
        }
    }
    ans[0]=0;
    for (i=1;i<=n;i++)
    {        ans[i]=ans[i-1]+1;
        for (j=1;j<=i;j++)
         if (ok[j][i]) ans[i]=mymin(ans[i],ans[j-1]);
    }
    printf("%d\n",ans[n]);
    return 0;
}

加了p数组的:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 200
#define M 40int bit[M],p[N][M],f[N][M],len[M],ans[N];
char s[N],str[M][M];bool ok[N][N];
int mymin(int x,int y){return (x<y)?x:y;}
int main()
{int n,m,i,j,k,l;gets(s+1);n=strlen(s+1);scanf("%d\n",&m);for (i=1;i<=m;i++) {scanf("%s",str[i]+1);len[i]=strlen(str[i]+1);}bit[0]=1;for (i=1;i<=22;i++) bit[i]=bit[i-1]<<1;memset(ok,false,sizeof(ok));for (i=1;i<=n;i++)for (j=1;j<=m;j++)for (k=1;k<=len[j];k++)if (s[i]==str[j][k]) p[i][j]|=bit[k-1];for (i=n;i>=1;i--)
    {        memset(f,0,sizeof(f));
        for (j=i;j<=n;j++)
        {            for (k=1;k<=m;k++)
            {                if (j!=i) f[j][k]=(f[j-1][k]<<1)&p[j][k];
                else f[j][k]=1&p[j][k];
                for (l=i;l<j;l++)
                 if (ok[l+1][j]) f[j][k]|=f[l][k];
                if (f[j][k]&bit[len[k]-1]) ok[i][j]=true;
            }
        }
    }
    ans[0]=0;
    for (i=1;i<=n;i++)
    {        ans[i]=ans[i-1]+1;
        for (j=1;j<=i;j++)
         if (ok[j][i]) ans[i]=mymin(ans[i],ans[j-1]);
    }
    printf("%d\n",ans[n]);
    return 0;
}

bzoj2121 字符串游戏相关推荐

  1. BZOJ2121 字符串游戏 【dp】

    题目链接 BZOJ2121 题解 dp怎么那么神呐QAQ 我们要求出最小字符串长度 我们设一个\(dp[i]\)表示前\(i\)个字符最后所形成的最短字符串长度 对于第\(i\)个字符,要么保留,就是 ...

  2. [BZOJ2121]-字符串游戏-字符串dp

    说在前面 觉得字符串dp都很神 题目 BZOJ2121传送门 看题可戳传送门 解法 首先me是看了dp定义才会做这道题的 这题-.me貌似写不出来思维过程,只能把做法说一说了,可能相关题目做多了之后会 ...

  3. BZOJ2121: 字符串游戏

    区间DP 用C[l][r]表示l~r是否能被全部删掉,f[l][r][k][x]表示l~r和第k个串匹配是否能匹配到第x位, 注意到小串的长度≤21,而且f是个bool变量,所以可以把x压成int, ...

  4. .net mvc actionresult 返回字符串_字符串游戏之无效的身份证

    出场人物介绍 小美:小学4年级学生,参加了学校的编程兴趣小组,已经了解了Python语言的基本语法,能够看懂一些简单的程序.她做事风风火火,对所有的事情都很好奇,喜欢打破砂锅问到底,是一个叫人又爱又恨 ...

  5. python 路径拼接字符串_字符串游戏之拼接字符串

    出场人物介绍 小美:小学4年级学生,参加了学校的编程兴趣小组,已经了解了Python语言的基本语法,能够看懂一些简单的程序.她做事风风火火,对所有的事物都很好奇,喜欢打破砂锅问到底,是一个叫人又爱又恨 ...

  6. bzoj 2121 字符串游戏

    BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删除,如果删除,则将删除后L ...

  7. bzoj 2121 字符串游戏(字符串dp)

    Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删除 ...

  8. 【2022 省选训练赛 Contest 17 A】字符串游戏(结论)

    字符串游戏 题目链接:2022 省选训练赛 Contest 17 A 题目大意 有一个字符串一开始是空的,两个人轮流操作在任意位置插入 0/1. 然后给你一个串 s,先手目标是使得 s 是字符串的子串 ...

  9. python身份证的秘密_Python算法之旅字符串游戏之身份证号的秘密

    最近在力扣(LeetCode)网闲逛,发现很多题目的官方题解都是用Python语言来描述的,这说明大家已经逐渐认识到Python语言描述算法的优越性:它语法简明,内置函数丰富,表述直截了当,可以用最简 ...

最新文章

  1. 1.4 w字,25 张图让你彻底掌握分布式事务原理
  2. CSS3绘制圆角矩形的简单示例
  3. 单页应用程序的Spring Boot静态Web资源处理
  4. windows 2003内存设置
  5. C语言基础知识之#pragma once
  6. 文字渐变效果:图层中的mask属性
  7. 22. Element lang 属性
  8. 冒泡排序详解(Java实现)
  9. Java实现单链表翻转
  10. 神经网络加速器设计研究:寒武纪DianNao论文阅读
  11. 按洲划分的国家和地区代码整理 包含:中文名 英文名 洲 首字母 两位英文代码 三位英文代码 三位数据代码 洲
  12. Node-RED中建立Websocket客户端连接
  13. 价值4500的国际版多语言点赞抖音分享点赞任务平台源码(十二种语言)
  14. 强大的grep用法详解:grep与正则表达式
  15. R语言survival包clogit函数构建条件logistic回归模型、summary函数查看模型汇总统计信息、通过似然比检验分析结果判断模型有无统计学意义
  16. 《细说PHP》第二版--读书笔记
  17. 软件poc测试方案,桌面云项目POC测试方案(12页)-原创力文档
  18. java简单代码实现_java的简单代码实现
  19. 2019 GDUT 新生专题Ⅲ L题
  20. 【图论】【网络流】费用流模型

热门文章

  1. redis常见问题及解决方案
  2. C# 将OFD转为PDF
  3. 「MoreThanJava」计算机发展史—从织布机到IBM
  4. 开源许可协议 Open Source License
  5. python3注释_python3的注释
  6. Java调用Zebra800条码打印机
  7. 两台笔记本电脑共享屏幕(其中一台电脑当做另外一台电脑的扩展屏幕,多屏显示)
  8. 自家的摇头扇线掉了 (电风扇的五根线怎么接)
  9. Java版 猜数字小游戏
  10. [ WARN] [1588040435.867625184]: MessageFilter [target=odom ]: Dropped 97.37% of messages so