首先如果我们能处理出来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了,这样就有了未定义行为。

/**************************************************************
    Problem: 2121
    User: BLADEVIL
    Language: C++
    Result: Accepted
    Time:132 ms
    Memory:158900 kb
****************************************************************/
 
//By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 200
#define maxm 1010
 
using namespace std;
 
struct node{
    int cnt,num;
    node *child[];
    node(){
        cnt=num=;
        memset(child,,sizeof child);
    }
}nodepool[maxm],*totnode,*rot;
 
char s[maxn];
int flag[maxn][maxn],vis[maxn][maxm][maxn],w[maxn];
int n,len;
 
 
void build_trie(){
    int j=;
    totnode=nodepool; rot=totnode++;
    scanf("%d",&n);
    char ch[maxn];
    while (n--) {
        scanf("%s",ch);
        int len=strlen(ch);
        node *t=rot;
        for (int i=;i<len;i++) {
            if (!t->child[ch[i]-'a']) t->child[ch[i]-'a']=totnode++,t->child[ch[i]-'a']->num=j++;
            t=t->child[ch[i]-'a'];
        }
        t->cnt=;
    }
}
 
void make(node *rot,int left,int right) {
    //printf("%d ",rot->num);
    if (rot->cnt) flag[left][right-]=;
    if (vis[left][rot->num][right]) return ;
    if (right>=len) return ;
    vis[left][rot->num][right]=;
    if (rot->child[s[right]-'a']) make(rot->child[s[right]-'a'],left,right+);
    for (int i=right;i<len;i++) if (flag[right][i]) make(rot,left,i+);
}
 
int main() {
    scanf("%s",s); len=strlen(s);
    build_trie();
    for (int i=len-;i>=;i--) make(rot,i,i);
    /*for (int i=0;i<len;i++) {
        for (int j=0;j<len;j++) printf("%d ",flag[i][j]);
        printf("\n");
    }*/
    w[]=;
    for (int i=;i<len;i++) {
        w[i+]=w[i]+;
        for (int j=;j<=i;j++)
            if (flag[j][i]) w[i+]=min(w[i+],w[j]);
        //printf("%d ",w[i]);
    }
    //printf("\n");
    printf("%d\n",w[len]);
    return ;
}

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. 【redis数据库学习】用JAVA连接redis数据库各种报错

    最近项目中,需要用到redis数据库,然后使用Jedis让JAVA连接redis. 首先,安装redis数据库,参考的是:http://www.runoob.com/redis/redis-insta ...

  2. EJB介绍

    EJB定义: 被称为java企业bean,服务器端组件,核心应用是部署分布式应用程序.用它部署的系统不限定平台.实际上EJB是一种产品,描述了应用组件要解决的标准. 标准: 可扩展 (Scalable ...

  3. ajax 请求 后台返回的文件流

    download(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可以使用POST方式,根据接口 xhr. ...

  4. apiDoc 入门

    网站 http://apidocjs.com/#demo Install npm install apidoc -g Run apidoc -i myapp/ -o apidoc/ -t mytemp ...

  5. jQuery的动画与特效

    显示与隐藏 show() 和 hide() 方法 动画效果的show() 和 hide() show(speed,[]callback) hide(speed,[]callback) speed:表示 ...

  6. Wannafly 挑战赛16 A 取石子

    题目描述 给出四堆石子,石子数分别为a,b,c,d.规定每次只能从堆顶取走石子,问取走所有石子的方案数. 输入描述: 在一行内读入四个由空格分隔的整数a,b,c,d, 输入均为不超过500的正整数 输 ...

  7. 用select模拟一个socket server成型版2

    1.字典队列测试 import queue msg_dic={} msg_dic[1]=queue.Queue() msg_dic[1].put('hello') msg_dic[1].put('bo ...

  8. [洛谷P3550][POI2013]TAK-Taxis

    题目大意:一条路上有三个点,$0$为起始位置,$d$为总部,$m$为家.有$n$辆车,每辆车最多行驶$x_i$,都从$d$出发,可以在任意位置结束,问最少几辆车可以到家. 题解:贪心,发现当人在$[0 ...

  9. BZOJ3670 [Noi2014]动物园 【KMP计数】

    3670: [Noi2014]动物园 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 3143  Solved: 1690 [Submit][Stat ...

  10. HDOJ.1075 What Are You Talking About(map)

    What Are You Talking About 点我跳转到题面 点我一起学习STL-MAP 题意分析 首先第一组START-END给出翻译的字典,第二组START-END给出一句话,查找里面出现 ...