Codechef STREDUC Reduce string Trie、bitset、区间DP
简化题意:给出一个长度为\(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的更多相关文章
- HDU 4570---Multi-bit Trie(区间DP)
题目链接 Problem Description IP lookup is one of the key functions of routers for packets forwarding and ...
- HDU 2476 String painter(区间DP)
String painter Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- String painter (区间dp)
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now ...
- HDU 2476 String painter (区间DP)
题意:给出两个串a和b,一次只能将一个区间刷一次,问最少几次能让a=b 思路:首先考虑最坏的情况,就是先将一个空白字符串刷成b需要的次数,直接区间DP[i][j]表示i到j的最小次数. 再考虑把a变成 ...
- UVA Live Archive 4394 String painter(区间dp)
区间dp,两个str一起考虑很难转移. 看了别人题解以后才知道是做两次dp. dp1.str1最坏情况下和str2完全不相同,相当于从空白串开始刷. 对于一个区间,有两种刷法,一起刷,或者分开来刷. ...
- String painter(区间DP)
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now ...
- HDOJ 题目2474 String painter(区间DP)
String painter Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- UVALive 4394 String painter ——(区间DP)
其实这个dp过程有点似懂非懂...代码如下: #include <stdio.h> #include <algorithm> #include <string.h> ...
- HDU4570:Multi-bit Trie(区间DP)
Problem Description IP lookup is one of the key functions of routers for packets forwarding and clas ...
随机推荐
- python之while循环/格式化输出/运算符/初始编码/成员变量
一.主要内容:1.while 循环 (难点)while 条件: 循环体 break: 直接跳出循环continue:停止当前本次循环,继续执行下一次循环.不会中断循环能让循环退出:(1)break ( ...
- React 入门学习笔记整理(八)—— todoList
APP.js import React, { Component,createRef,Fragment} from 'react'; import Todos from './components/t ...
- loadrunner 场景设计-设置结果文件保存路径
场景设计-设置结果文件保存路径 by:授客 QQ:1033553122 Results->Results settings Results Name 结果文件夹名称 Directory 指定结果 ...
- 【转】HTTP协议之multipart/form-data请求分析
原文链接:http://blog.csdn.net/five3/article/details/7181521 首先来了解什么是multipart/form-data请求: 根据http/1.1 rf ...
- Django 拾遗
1.python_2_unicode_compatible装饰器 from django.db import models from django.utils.encoding import pyth ...
- pycharm运行Django发生AppRegistryNotReady: Apps aren't loaded yet.
pycharm中运行django默认情况下并不是执行项目的,所以如果在非manage.py,会发生异常. raise AppRegistryNotReady("Apps aren't loa ...
- ALSA声卡驱动的DAPM(一)-DPAM详解
最近使用tinymix 调试相应的音频通道,但是一直不知道音频通道的原理是什么.所以百度了一下,百度结果是与DPAM有关. 一.DAPM简介: DAPM是Dynamic Audio Power Man ...
- windows防火墙安全设置指定ip访问指定端口
场景摘要: 1.我有三台腾讯云服务器 2.我日常办公网络的ip换了 3.我在腾讯云上面改了安全规则,也不能访问我A服务器的21,1433等端口 4.开始我以为是办公网络的安全设置问题 5.我进B服务器 ...
- 自己动手写waf指纹识别
import requests import re def target_url(scan_url): xssstring = '<script>alert(1)</script&g ...
- mysql排序索引优化
为排序使用索引 KEY a_b_c (a,b,c) order by 能使用索引最左前缀 -order by a -order by a,b -order by a,b,c -order by a d ...