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. SAP MM 并非奇怪现象之MB5B报表查不到某一笔出库记录?

    物料号:1301002696 工厂代码:2160 MB5B,如下查询条件, 查询结果中,期初与期末库存数量都是0,期间的出库入库数量都是0.事实上该物料期初应该是有库存的.并且我用MB51相同时间段查 ...

  2. Gartner2017年BI研究计划曝光,来看看他研究的都是啥?

    文 | 水手哥 本文出自:知乎专栏<帆软数据应用研究院>——数据干货&资讯集中地   近日,Gartner发布了<Analytics and Business Intelli ...

  3. Linux 学习笔记之超详细基础linux命令 Part 13

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 12---------------- ...

  4. couldn't locate lint-gradle-api-26.1.2.jar for flutter project

    Could not find com.android.tools.lint:lint-gradle:26.1.2 当我尝试构建发行版本APK 时导致报这种错误,无法发行,针对自己的项目作出了相关修改, ...

  5. (网页)JS和CSS不缓存方法,时间戳

    <link ..... href=".....css?time"+new Date()> <script type="text/javascript&q ...

  6. 【CSS基础】实现 div 里的内容垂直水平居中

    方案一: 所有内容垂直水平居中 兼容性:IE8+. 条件:内容宽度和高度可以未知,可以是多行文字.图片.div. 描述:使用table-cell + vertical-align , html代码见文 ...

  7. .NET 控制Windows文件和目录访问权限研究(FileSystemAccessRule)

    前一段时间学习了.net 控制windows文件和目录权限的相关内容,期间做了一些总结.想把这方面的研究跟大家分享,一起学习.其中不免得有些用词不太标准的地方,希望大家留言指正,我加以修改. 首先,我 ...

  8. python第三天 变量 作业

    作业1,模拟登陆:1. 用户输入帐号密码进行登陆2. 用户信息保存在文件内3. 用户密码输入错误三次后锁定用户 使用文件:user_file.txt  用户列表文件.     格式:{'张三':'12 ...

  9. do-while语句及for语句(初学者)

    1.do-while语句的一般形式为: do 语句 while(表达式): 这个循环与while循环的不同在于:它先执行循环中的语句,然后再判断这个表达式是否为真,如果为真则继续循环:如果为假,则中止 ...

  10. Tomcat 访问页面或服务器异常,请检查这些方面

    若还没有部署网站,请检查 防火墙是否关闭 数据库服务是否打开 浏览器访问的地址和端口是否正确 tomcat 配置文件中的端口是否发生冲突,换一个试试 若出现的是"拒绝连接",检查阿 ...