VJ传送门

简化题意:给出一个长度为\(l\)的模板串\(s\)与若干匹配串\(p_i\),每一次你可以选择\(s\)中的一个出现在集合\(\{p_i\}\)中的子串将其消去,其左右分成的两个串拼接在一起形成新的串\(s\)。问如是进行消除,最后\(s\)的最短长度。


当时没想到做法,现在看起来还是比较简单欸……

考虑计算出所有可以被消除的区间然后\(DP\)

先将所有匹配串插入到Trie树上,设\(f_{i,j,k}\)表示子串\(s_{i,j}\)通过任意消除得到的串是否能对应到\(Trie\)树的\(k\)号节点上。转移分两种:

①在子串\(s_{i,j-1}\)之后接上\(s_j\),直接在\(Trie\)树上找是否存在对应的儿子;②存在某个子串\(s_{x,j}(x > i)\)可以被消除,那么\(\forall k, f_{i,j,k} |= f_{i,x-1,k}\)

计算完成后,如果存在\(k\)使得某一个匹配串在\(Trie\)树上对应节点\(k\)且\(f_{i,j,k}=1\),那么意味着子串\(s_{i,j}\)可以通过消除消除成一个匹配串,那么我们认为子串\(s_{i,j}\)可以被消除,且令\(f_{i,j,root}=1\)表示可以消除为空串。

发现复杂度为\(O(l^3\sum|p_i|)\),但是转移②可以使用bitset进行优化,复杂度就会降为\(O(\frac{l^3 \sum |p_i|}{32})\),而且状态不满,就能很快的跑过了。

计算出可以被消除的区间然后区间DP算出答案。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cmath>
//This code is written by Itst
using namespace std; inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return f ? -a : a;
} struct node{
int ch[26];
}Trie[610];
int dp[251] , cntN = 1 , N , S;
bool can[251][251];
bitset < 610 > f[251][251];
char s[251] , mod[31];
vector < int > End; void insert(){
int L = strlen(mod + 1) , cur = 1;
for(int i = 1 ; i <= L ; ++i){
if(!Trie[cur].ch[mod[i] - 'a'])
Trie[cur].ch[mod[i] - 'a'] = ++cntN;
cur = Trie[cur].ch[mod[i] - 'a'];
}
End.push_back(cur);
} int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
scanf("%s" , s + 1);
N = strlen(s + 1);
for(int i = 1 ; i <= N ; ++i)
f[i][i - 1][1] = 1;
S = read();
for(int i = 1 ; i <= S ; ++i){
scanf("%s" , mod + 1);
insert();
}
for(int i = 1 ; i <= N ; ++i)
for(int j = i ; j ; --j){
for(int k = 1 ; k <= cntN ; ++k)
if(f[j][i - 1][k] && Trie[k].ch[s[i] - 'a'])
f[j][i][Trie[k].ch[s[i] - 'a']] = 1;
for(int k = j + 1 ; k <= i ; ++k)
if(can[k][i])
f[j][i] |= f[j][k - 1];
for(int k = 0 ; k < S ; ++k)
if(f[j][i][End[k]])
f[j][i][1] = 1;
can[j][i] = f[j][i][1];
}
for(int i = 1 ; i <= N ; ++i){
dp[i] = dp[i - 1] + 1;
for(int j = i ; j >= 0 ; --j)
if(can[j][i])
dp[i] = min(dp[i] , dp[j - 1]);
}
cout << dp[N];
return 0;
}

Codechef STREDUC Reduce string Trie、bitset、区间DP的更多相关文章

  1. HDU 4570---Multi-bit Trie(区间DP)

    题目链接 Problem Description IP lookup is one of the key functions of routers for packets forwarding and ...

  2. HDU 2476 String painter(区间DP)

    String painter Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...

  3. String painter (区间dp)

    There are two strings A and B with equal length. Both strings are made up of lower case letters. Now ...

  4. HDU 2476 String painter (区间DP)

    题意:给出两个串a和b,一次只能将一个区间刷一次,问最少几次能让a=b 思路:首先考虑最坏的情况,就是先将一个空白字符串刷成b需要的次数,直接区间DP[i][j]表示i到j的最小次数. 再考虑把a变成 ...

  5. UVA Live Archive 4394 String painter(区间dp)

    区间dp,两个str一起考虑很难转移. 看了别人题解以后才知道是做两次dp. dp1.str1最坏情况下和str2完全不相同,相当于从空白串开始刷. 对于一个区间,有两种刷法,一起刷,或者分开来刷. ...

  6. String painter(区间DP)

    There are two strings A and B with equal length. Both strings are made up of lower case letters. Now ...

  7. HDOJ 题目2474 String painter(区间DP)

    String painter Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  8. UVALive 4394 String painter ——(区间DP)

    其实这个dp过程有点似懂非懂...代码如下: #include <stdio.h> #include <algorithm> #include <string.h> ...

  9. HDU4570:Multi-bit Trie(区间DP)

    Problem Description IP lookup is one of the key functions of routers for packets forwarding and clas ...

随机推荐

  1. 【读书笔记】iOS-iOS敏捷开发

    敏捷开发分为几个不同的门派,如:Scrum,XBreed,极限编程(XP Extreme Programming)和水晶方法等. 参考资料:<iOS传感器应用开发最佳实践>  

  2. IE9获取file控件的本地文件路径

    最近发现,在IE9下,公司网站的本地图片预览都无法正常显示,经过测试发现,原因在于IE9下无法获取file控件的文件路径. 以前的代码如下: var strPic = fileImg.value; i ...

  3. JavaScript日期排序

    //日期排序 function sortDownDate(a, b) { return Date.parse(a.received) - Date.parse(b.received); } funct ...

  4. CSS3创建圆圈进度条

    最近在工作中需要做一个圆圈倒计时,刚开始的想法是做个纯数字的倒计时即可,可是需求觉得这个不太好看,想加个倒计时进度条.于是就有了接下来的分析过程... 我们知道CSS3可以很方便的画圆,圆环,然后在加 ...

  5. 洗礼灵魂,修炼python(40)--面向对象编程(10)—定制魔法方法+time模块

    定制魔法方法 1.什么是定制魔法方法 首先定制是什么意思呢?其实就是自定义了,根据我们想要的要求来自定义.而在python中,其实那些所谓的内置函数,内置方法,内置属性之类的其实也是自定义出来的,不过 ...

  6. [MapReduce_add_3] MapReduce 通过分区解决数据倾斜

    0. 说明 数据倾斜及解决方法的介绍与代码实现 1. 介绍 [1.1 数据倾斜的含义] 大量数据发送到同一个节点进行处理,造成此节点繁忙甚至瘫痪,而其他节点资源空闲 [1.2 解决数据倾斜的方式] 重 ...

  7. 12LaTeX学习系列之---LaTex的图片插入

    目录 目录 前言 (一)插图的基本语法 (二)插入的基本设置 1.说明: 2.源代码: 3.输出效果 (三)查看文档 目录 本系列是有关LaTeX的学习系列,共计19篇,本章节是第12篇. 前一篇:1 ...

  8. [Eclipse+PyDev]ImportError: DLL load failed:找不到指定的模块 解决方案

    1. 环境 Eclipse 4.4.2 Python 3.5 Window 8.1 2. 问题 在代码中import numpy时,提示 " ImportError: DLL load fa ...

  9. centos 上安装phpstorm

    phpstorm在centos上运行依赖JDK,所以先安装JDK环境. 假如是centos自带的openjdk,直接卸载,不支持phpstorm. 下载jdk-7u45-linux-i586.tar. ...

  10. Luogu P4707 重返现世

    题目描述 为了打开返回现世的大门,Yopilla 需要制作开启大门的钥匙.Yopilla 所在的迷失大陆有 \(n\) 种原料,只需要集齐任意 \(k\) 种,就可以开始制作. Yopilla 来到了 ...