首先如果我们能处理出来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 ;
}

最新文章

  1. jQuery-1.9.1源码分析系列(七) 钩子(hooks)机制及浏览器兼容
  2. mysql安装,配置。
  3. sublime安装package control组件
  4. 【iCore3 双核心板】例程十六:USB_HID实验——双向数据传输
  5. PHP安装rrdtool扩展
  6. 模板短信接口调用java,pythoy版(一) 网易云信
  7. Python 信号量
  8. Hibernate4.x之映射关系--继承映射
  9. iOS中懒加载
  10. github教程--廖雪峰的官方网站
  11. 【新提醒】N820 N821 android 4.2 V1.1版 - 大V综合交流区 - 360官方论坛
  12. 打造简易可扩展的jQuery/CSS3 Tab菜单
  13. 震荡信号Simulink仿真
  14. Docker for windows10 配置镜像加速
  15. 福州大学软工 1715 | K 班 - 启航
  16. pip相关工具使用小结
  17. 带你走进CSS定位详解
  18. python国外博客推荐
  19. 使用jquery.uploadify上传文件
  20. 关于客户端调用后台事件__doPostBack函数的使用

热门文章

  1. 用SC命令 添加或删除windows服务提示OpenSCManager 失败5 拒绝访问
  2. 3dContactPointAnnotationTool开发日志(二)
  3. lol人物模型提取(二)
  4. animate.css与wow.js制作网站动效
  5. 面试:谈谈你对jQuery的理解
  6. Oracle中预定义角色有哪些?
  7. 一致性Hash算法(Consistent Hash)
  8. asp.net mvc4中Json的应用
  9. CentOS 文件及目录等
  10. java动态代理(JDK和CGLIB)笔记