AC自动机+状态DP。

虽然很明显的AC自动机+状态DP题,但要分析问题上还是欠缺一点了。一直在犹豫枚举每一个字符选或不选的状态会不会超时,以为会达到状态有2^n,但其实根本没有。因为有很多状态是可以重复的,这是由于每一位字符选或不选,都只能转移动自动机的固定位置,所以,状态是有限的。状态压缩是为了确定必须出现的串是否全部出现。于是可以设状态:

dp[i][j][k]为当前处理到第i个字符,处于自动机的j状态,k为必须出现的字符串是否出现的情况。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std;
const int root=0;
const int inf=1<<30;
int trie[1650][26];
int fail[1650];
int tag[1650],tot;
int que[1650],head,tail;
int kill[1650],must[1650],score[1650];
int need;
struct Status{
int act,sc;
void init(){
act=inf,sc=-inf;
}
}dp[2][1650][260];
char str[110]; void init(int cur){
for(int i=0;i<=tot;i++){
for(int k=0;k<(1<<(need+1));k++)
dp[cur][i][k].init();
}
} void AddTrie(char *s,int sc){
int len=strlen(s);
int i=0,p=root;
while(len--){
if(trie[p][s[i]-'a']==-1){
trie[p][s[i]-'a']=++tot;
kill[tot]=must[tot]=0;
memset(trie[tot],-1,sizeof(trie[tot]));
}
p=trie[p][s[i]-'a'];
i++;
}
if(sc==999){must[p]|=(1<<need);}
else if(sc==-999) kill[p]=1;
else {
score[p]+=sc;
}
} void build_ac(){
head=tail=0;
que[tail++]=root;
while(head!=tail){
int tmp=que[head++];
int p=-1;
for(int i=0;i<26;i++){
if(trie[tmp][i]!=-1){
if(tmp==root) fail[trie[tmp][i]]=root;
else{
p=fail[tmp];
while(p!=-1){
if(trie[p][i]!=-1){
fail[trie[tmp][i]]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-1) fail[trie[tmp][i]]=root;
}
if(kill[fail[trie[tmp][i]]]) kill[trie[tmp][i]]=1;
if(must[fail[trie[tmp][i]]]) must[trie[tmp][i]]|=must[fail[trie[tmp][i]]];
if(score[fail[trie[tmp][i]]]) score[trie[tmp][i]]+=score[fail[trie[tmp][i]]];
que[tail++]=trie[tmp][i];
}
else{
if(tmp==root) trie[tmp][i]=root;
else{
p=fail[tmp];
while(p!=-1){
if(trie[p][i]!=-1){
trie[tmp][i]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-1) trie[tmp][i]=root;
}
}
}
}
} void Cal(){
int cur=0,next=1;
init(cur); init(next);
int len=strlen(str);
dp[cur][0][0].act=0; dp[cur][0][0].sc=0;
for(int i=0;i<len;i++){
// cout<<i<<endl;
for(int j=0;j<=tot;j++){
for(int k=0;k<(1<<(need+1));k++){
if(dp[cur][j][k].act>=inf) continue;
int pn=trie[j][str[i]-'a'];
if(kill[pn]){
if(dp[cur][j][k].act+1<dp[next][j][k].act){
dp[next][j][k].act=dp[cur][j][k].act+1;
dp[next][j][k].sc=dp[cur][j][k].sc;
}
else if(dp[cur][j][k].act+1==dp[next][j][k].act&&dp[cur][j][k].sc>dp[next][j][k].sc){
dp[next][j][k].sc=dp[cur][j][k].sc;
}
}
else{
int tmpk=k|must[pn];
if(dp[cur][j][k].act<dp[next][pn][tmpk].act){
dp[next][pn][tmpk].act=dp[cur][j][k].act;
dp[next][pn][tmpk].sc=dp[cur][j][k].sc+score[pn];
}
else if(dp[cur][j][k].act==dp[next][pn][tmpk].act&&dp[cur][j][k].sc+score[pn]>dp[next][pn][tmpk].sc){
dp[next][pn][tmpk].sc=dp[cur][j][k].sc+score[pn];
}
if(dp[cur][j][k].act+1<dp[next][j][k].act ){
dp[next][j][k].act=dp[cur][j][k].act+1;
dp[next][j][k].sc=dp[cur][j][k].sc;
}
else if(dp[cur][j][k].act+1==dp[next][j][k].act&&dp[cur][j][k].sc>dp[next][j][k].sc){
dp[next][j][k].sc=dp[cur][j][k].sc;
}
}
}
} init(cur);
cur^=1;
next^=1;
}
int minact=inf,maxsc=-inf;
for(int i=0;i<=tot;i++){
if(dp[cur][i][(1<<(need+1))-1].act<minact){
minact=dp[cur][i][(1<<(need+1))-1].act;
maxsc=dp[cur][i][(1<<(need+1))-1].sc;
}
else if(dp[cur][i][(1<<(need+1))-1].act==minact&&maxsc<dp[cur][i][(1<<(need+1))-1].sc)
maxsc=dp[cur][i][(1<<(need+1))-1].sc;
}
if(minact>=inf)
puts("Banned");
else cout<<minact<<" "<<maxsc<<endl;
} int main(){
int T,icase=0;
char s[20];int sc;
scanf("%d",&T);
while(T--){
int n;
tot=0,need=-1;
memset(trie[tot],-1,sizeof(trie[tot]));
memset(score,0,sizeof(score));
memset(kill,0,sizeof(kill));
memset(must,0,sizeof(must));
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s%d",s,&sc);
if(sc==999) need++;
AddTrie(s,sc);
}
// cout<<"YES"<<endl;
build_ac();
scanf("%s",str);
printf("Case %d: ",++icase);
Cal();
}
return 0;
}

  

HDU 4534的更多相关文章

  1. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  2. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  3. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  4. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  5. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  6. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

  7. hdu 4481 Time travel(高斯求期望)(转)

    (转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...

  8. HDU 3791二叉搜索树解题(解题报告)

    1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...

  9. hdu 4329

    problem:http://acm.hdu.edu.cn/showproblem.php?pid=4329 题意:模拟  a.     p(r)=   R'/i   rel(r)=(1||0)  R ...

随机推荐

  1. python 生成器函数.推导式.生成器表达式

    一.生成器 什么是生成器,生成器的实质就是迭代器 在python中有三种方式来获取生成器: 1.通过生成器函数 2.通过各种推导式来实现生成器 3.通过数据的转换也可以获取生成器 1 def func ...

  2. ACM_堆箱子咯(栈)

    堆箱子咯 Time Limit: 2000/1000ms (Java/Others) Problem Description: 双十一大家都在买买买,可忙坏了快递小哥了.zl和皮卡鸡在大伙在剁手的时候 ...

  3. EF--DBFirst

    EF框架有三种基本的方式:DB First,Model First,Code First.这里简单的说一下DB First,适合没有基础的同学照着做,学习基础的东西. DatabaseFirst就是围 ...

  4. 解决Android弹出软键盘导致的问题

    一.当Activity启动后EditText直接获取了焦点,此时软键盘会自动弹出,这种体验并不是很好,因此要做的Activity启动不自动弹出软键盘,只需要在Manifest中对应的Activity添 ...

  5. CNN结构:Windows使用FasterRCNN-C++版本

    参考文章:Windows下VS2013 C++编译测试faster-rcnn. 本文与作者的所写方法有些许不同,欲速则不达,没有按照作者的推荐方法,绕了个弯弯. Windows版本纯C++版本的Fas ...

  6. 常见Android安装启动失败问题

    1.INSTALL_FAILED_VERSION_DOWNGRADE版本过低2.Failed to install Funm_AND.apk on device 'QWOJLVR8KNHYA6NR': ...

  7. xamarin.forms模拟rem动态大小值,实现屏幕适配

    开发app的时候,比较麻烦的地方,就是处理屏幕适配,比如文字设为12的大小,测试的时候,看得文字挺正常,可是,放到高分辨率设备一看,文字就变得特别小, 怎样实现随着分辨率变大或者变小,所有的size数 ...

  8. nginx+tomcat实现负载均衡集群

    一台tomcat站点由于可能出现单点故障及无法应付过多客户复杂多样的请求等问题,不能单独应用于生产环境下 所以需要一套可靠的解决方案来完善web站点架构 而Nginx只能访问静态页面,如果需要动态需要 ...

  9. react typescript 子组件给父组件传值

    //父组件 import * as React from 'react'import { Input } from 'antd'const Search = Input.Searchimport &q ...

  10. 开发LED屏幕页面遇到的问题

    上上个礼拜公司的展销会活动需要一个展示在LED大屏幕的页面,顶部显示平台交易总金额,左右两边分别是厂家和买家实时交易记录,具体页面长下面这个样子 需求评审的时候产品说顶部的总金额要有一个数字滚动或者翻 ...