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. Python 再谈变量作用域与变量引用

    再谈变量作用域与变量引用 by:授客 QQ:1033553122 module3.py #!/usr/bin/env python # -*- coding:utf-8 -*-   __author_ ...

  2. JS笔记(二):对象

    (一) 对象 对象是JS的基本数据类型,类似于python的字典.然而对象不仅仅是键值对的映射,除了可以保持自有的属性,JS对象还可以从一个称为原型的对象继承属性,对象的方法通常是继承的属性.(这种对 ...

  3. 【redis专题(6)】命令语法介绍之hash

    可以把hash看做一个数组hset array key1 value2;,该数据类型特别适用于存储 增 hset key field value 作用: 把key中filed域的值设为value 注: ...

  4. 洗礼灵魂,修炼python(25)--自定义函数(6)—从匿名函数进阶话题讲解中解析“函数式编程”

    匿名函数进阶 前一章已经说了匿名函数,匿名函数还可以和其他内置函数结合使用 1.map map():映射器,映射 list(map(lambda x:x*2,range(10))) #把range产生 ...

  5. 计算机硬件基本知识及Linux的常用命令

    ------------------1. 计算机硬件基本知识------------------ CPU - 寄存器 - L1/L2/L3 - 内存 - 硬盘 - 互联网下载/其他存储介质传输 寄存器 ...

  6. SonarQube 配置 LDAP(AD域)

    安装插件 1.下载 LDAP Plugin 插件,地址:https://docs.sonarqube.org/display/SONARQUBE67/LDAP+Plugin2.将下载的插件,放到 SO ...

  7. ABAP性能和优化

    哪些工具可以用于性能优化? ST05-性能追踪.包含SQL追踪加RFC,队列和缓存追踪.SQL追踪主要用于测量程序中select语句的性能. SE30-运行时分析.用于测量应用的性能. SAT是过时的 ...

  8. 使用CefSharp的一些需要注意的点

    程序关闭的时候一定要加上: CefSharp.Cef.Shutdown(); 因为关闭的时候,不将浏览器关闭的话,会阻塞主线程导致报错. 修复CefSharp浏览器组件中文输入的bug // brow ...

  9. EasyUI设置选中复选框

    //设置选中 $('#isBind').prop('checked', true); //获取是否选中 var isChecked = $('#isBind').prop('checked'); if ...

  10. Android Studio入门问题汇总

    1.如何设置 AS 中的字体大小 2.如何切换 AS 的皮肤颜色,默认为黑色,修改为白色,改为 default 3.首次安装 Android Studio并打开时,如果创建了一个新工程并将工程保存在另 ...