首先如果我们能处理出来i,j段能不能消掉,这样就可以直接dp转移了,设w[i]为前i为最少剩下多少,那么w[i]=w[j-1] (flag[j][i])。

  现在我们来求flag[i][j],首先我们可以把字符串组建立trie然后处理在串L中从left位置开始的所有的flag,那么我们可以在trie上一直往下走,每到一个标记的点就将当前的flag[left][right]设为1,那么这样可以处理出连续可以消掉的字符串,然后就处理对于类似L为abcde,字符串组为ade,bc这样可以先消一个,然后再消的情况,这样我们可以发现,如果对于当前的left,right存在flag[i][right]=1,那么就是这样的情况,那么我们直接递归处理left,i就好了,但是我们发现这里的flag[i][right]的i是大于left的,所以我们在处理以某个为开头的所有的flag的时候需要倒序处理。

  有一个优化,在同一个left时,我们在处理flag的时候有两种拓展情况,所以对于每一个i我们记录一个vis[i][j],表示在当前的left,i节点,right为j的情况是否访问过,这样有访问的情况return就好了。

  反思:开始没加优化,挺快就a了,后来加了优化之后,因为我用的指针存的trie,所以vis数组中节点的编号需要对于每个指针都存一个编号,但是这个编号不知道怎么回事儿,一申请就re,后面的按照不加优化的写,只是在node那在cnt之前申请一个num就会re,在cnt之后申请就没问题,调了半个上午也不知道怎么回事儿= =,原来一直是这么写的啊。

  反思2:后来发现是return的条件为right>=len,写成right>len了,这样就有了未定义行为。

  1. /**************************************************************
  2.     Problem: 2121
  3.     User: BLADEVIL
  4.     Language: C++
  5.     Result: Accepted
  6.     Time:132 ms
  7.     Memory:158900 kb
  8. ****************************************************************/
  9.  
  10. //By BLADEVIL
  11. #include <cstdio>
  12. #include <cstring>
  13. #include <algorithm>
  14. #define maxn 200
  15. #define maxm 1010
  16.  
  17. using namespace std;
  18.  
  19. struct node{
  20.     int cnt,num;
  21.     node *child[];
  22.     node(){
  23.         cnt=num=;
  24.         memset(child,,sizeof child);
  25.     }
  26. }nodepool[maxm],*totnode,*rot;
  27.  
  28. char s[maxn];
  29. int flag[maxn][maxn],vis[maxn][maxm][maxn],w[maxn];
  30. int n,len;
  31.  
  32.  
  33. void build_trie(){
  34.     int j=;
  35.     totnode=nodepool; rot=totnode++;
  36.     scanf("%d",&n);
  37.     char ch[maxn];
  38.     while (n--) {
  39.         scanf("%s",ch);
  40.         int len=strlen(ch);
  41.         node *t=rot;
  42.         for (int i=;i<len;i++) {
  43.             if (!t->child[ch[i]-'a']) t->child[ch[i]-'a']=totnode++,t->child[ch[i]-'a']->num=j++;
  44.             t=t->child[ch[i]-'a'];
  45.         }
  46.         t->cnt=;
  47.     }
  48. }
  49.  
  50. void make(node *rot,int left,int right) {
  51.     //printf("%d ",rot->num);
  52.     if (rot->cnt) flag[left][right-]=;
  53.     if (vis[left][rot->num][right]) return ;
  54.     if (right>=len) return ;
  55.     vis[left][rot->num][right]=;
  56.     if (rot->child[s[right]-'a']) make(rot->child[s[right]-'a'],left,right+);
  57.     for (int i=right;i<len;i++) if (flag[right][i]) make(rot,left,i+);
  58. }
  59.  
  60. int main() {
  61.     scanf("%s",s); len=strlen(s);
  62.     build_trie();
  63.     for (int i=len-;i>=;i--) make(rot,i,i);
  64.     /*for (int i=0;i<len;i++) {
  65.         for (int j=0;j<len;j++) printf("%d ",flag[i][j]);
  66.         printf("\n");
  67.     }*/
  68.     w[]=;
  69.     for (int i=;i<len;i++) {
  70.         w[i+]=w[i]+;
  71.         for (int j=;j<=i;j++)
  72.             if (flag[j][i]) w[i+]=min(w[i+],w[j]);
  73.         //printf("%d ",w[i]);
  74.     }
  75.     //printf("\n");
  76.     printf("%d\n",w[len]);
  77.     return ;
  78. }

bzoj 2121 DP的更多相关文章

  1. bzoj 3622 DP + 容斥

    LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[ ...

  2. 【BZOJ 2121】字符串游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=2121 dp,设\(f(i,j,k,l)\)表示原串i到j这个子串能否被删成第k个串的长度为l的前缀. ...

  3. 【BZOJ 2121】 (字符串DP,区间DP)

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

  4. BZOJ 2121: 字符串游戏 区间DP + 思维

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

  5. BZOJ#2121. 字符串游戏 [区间dp]

    // powered by c++11 // by Isaunoya #include<bits/stdc++.h> #define rep(i , x , y) for(register ...

  6. BZOJ - 1003 DP+最短路

    这道题被马老板毒瘤了一下,TLE到怀疑人生 //然而BZOJ上妥妥地过了(5500ms+ -> 400ms+) 要么SPFA太玄学要么是初始化block被卡到O(n^4) 不管了,不改了 另外D ...

  7. BZOJ 2431 & DP

    题意:求逆序对数量为k的长度为n的排列的个数 SOL: 显然我们可以对最后一位数字进行讨论,判断其已经产生多少逆序对数量,然后对于前n-1位同样考虑---->每一个长度的排列我们都可以看做是相同 ...

  8. bzoj 1791 DP

    首先对于一棵树我们可以tree_dp来解决这个问题,那么对于环上每个点为根的树我们可以求出这个树的一端为根的最长链,并且在tree_dp的过程中更新答案.那么我们对于环,从某个点断开,破环为链,然后再 ...

  9. bzoj 1592 dp

    就是dp啊 f[i][j]表示到第i位,最后一位高度是j的最小花费 转移::f[i][j]=minn(f[i-1][k])+abs(a[i]-num[j]);(k<=j) #include< ...

随机推荐

  1. <Effective C++>读书摘要--Ctors、Dtors and Assignment Operators<一>

    <Item 5> Know what functions C++ silently writes and calls 1.If you don't declare them yoursel ...

  2. 如何设置windows 2003的最大远程连接数

    在Windows 2003系统上的远程桌面实际上就是终端服务,虽然远程桌面最初在Windows XP上就已经存在,但由于Windows XP的远程桌面功能,只能提供一个用户使用计算机,因此使用率并不高 ...

  3. sublime Text3 如何自动排版代码

    安装 html beautiful 然后按ctrl+shift+alt+f

  4. JSTL标签之核心标签

    JSTL(JSP Standard Tag Library ,JSP标准标签库)是一个实现 Web应用程序中常见的通用功能的定制标记库集,这些功能包括迭代和条件判断.数据管理格式化.XML 操作以及数 ...

  5. zk分布锁的java实现

    只做记录,直接上代码 父类: package com.ylcloud.common.lock; import com.alibaba.fastjson.JSON; import org.I0Itec. ...

  6. Spline样条函数 //C++关键字:operator // 重载函数 // 隐含的this指针 // 指针和const限定符

    在数学学科数值分析中,样条是一种特殊的函数,由多项式分段定义.样条插值是使用一种名为样条的特殊分段多项式进行插值的形式.由于样条插值可以使用低阶多项式样条实现较小的差值误差,这样就避免了使用高阶多项式 ...

  7. 转:概率主题模型简介 --- ---David M. Blei所写的《Introduction to Probabilistic Topic Models》的译文

    概率主题模型简介 Introduction to Probabilistic Topic Models      转:http://www.cnblogs.com/siegfang/archive/2 ...

  8. 注解失效,@SpringBootApplication 失效,引入包失效

    因为同时修改两个springboot工程,其中把一个工程的版本调整到2.0.2.RELEASE,然后坑爹的事情出现了,所有springboot工程的@SpringBootApplication失效, ...

  9. 【题解】CF#280 C-Game on Tree

    感觉对期望也一无所知……(:′⌒`)╮(╯﹏╰)╭ 一直在考虑怎么dp,最后看了题解——竟然是这样的???[震惊]但是看了题解之后,觉得确实很有道理…… 我们可以考虑最后答案的组成,可以分开计算不同的 ...

  10. [WC2005]友好的生物

    description 洛谷 求 \[max_{1\le i<j\le n}\{\sum_{s=1}^{k-1}(C_s-|D_{is}-D_{js}|)-(C_k-|D_{ik}-D_{jk} ...