您的位置:首页 > 其它

HDU 4534 郑厂长系列故事——新闻净化(AC自动机+DP)

2013-07-29 16:36 281 查看
题目链接

蛋碎了,开始理解错题意的,以为跟上个题一样要替换。。。然后发现删除我不会啊,然后听宝哥讲了讲转移过程后,也不算难理解,主要是被前面的题给局限住思维了。

然后就是漫长的debug过程,手动构造数据,构造的我心碎了,最后看别人代码才发现错误,别人的代码实现方式和我明显不是一个风格的,我看的也很纠结啊。。。

在AC自动机构造关系的时候,开始只注意了-999的转移,然后慢慢debug后+上权值的转移,最后才发现999串的转移也要有,折腾了一天,终于过了。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define N 2000
#define INF 10000000
int t;
int trie
[26];
int o
;
int que
;
int flag
;
int fail
;
int wa
;
int dp1
[256];
int dp2
[256];
int goal1
[256];
int goal2
[256];
int num;
void CL()
{
num = 0;
memset(trie,-1,sizeof(trie));
memset(o,0,sizeof(o));
memset(flag,0,sizeof(flag));
memset(wa,0,sizeof(flag));
t = 1;
}
void insert(char *str,int x)
{
int i,root,len,sum;
root = 0;
len = strlen(str);
sum = 0;
for(i = 0; i < len; i ++)
{
if(trie[root][str[i]-'a'] == -1)
trie[root][str[i]-'a'] = t ++;
root = trie[root][str[i]-'a'];
}
if(x == 999)
{
flag[root] = 1<<num;
num ++;
}
else if(x == -999)
{
wa[root] = 1;
}
else
o[root] += x;
}
void build_ac()
{
int head,tail,front,i;
head = tail = 0;
for(i = 0; i < 26; i ++)
{
if(trie[0][i] != -1)
{
fail[trie[0][i]] = 0;
que[tail++] = trie[0][i];
}
else
{
trie[0][i] = 0;
}
}
while(head != tail)
{
front = que[head++];
flag[front] |= flag[fail[front]];
wa[front] |= wa[fail[front]];
o[front] += o[fail[front]];
for(i = 0; i < 26; i ++)
{
if(trie[front][i] != -1)
{
que[tail++] = trie[front][i];
fail[trie[front][i]] = trie[fail[front]][i];
}
else
{
trie[front][i] = trie[fail[front]][i];
}
}
}
}
int main()
{
int cas = 1,i,j,k,n,len,x,d;
char str[101];
scanf("%d",&d);
while(d--)
{
scanf("%d",&n);
CL();
for(i = 1; i <= n; i ++)
{
scanf("%s%d",str,&x);
insert(str,x);
}
build_ac();
scanf("%s",str);
len = strlen(str);
for(i = 0; i <= t; i ++)
{
for(j = 0; j < (1<<num); j ++)
{
dp1[i][j] = INF;
dp2[i][j] = INF;
goal1[i][j] = -INF;
goal2[i][j] = -INF;
}
}
dp1[0][0] = 0;
goal1[0][0] = 0;
for(i = 0; i < len; i ++)
{
for(j = 0; j < t; j ++)
{
if(wa[j]) continue;
for(k = 0; k < (1<<num); k ++)
{
if(dp1[j][k] == INF) continue;
if(dp2[j][k] > dp1[j][k] + 1)
{
dp2[j][k] = dp1[j][k] + 1;
goal2[j][k] = goal1[j][k];
}
else if(dp2[j][k] == dp1[j][k] + 1)
{
goal2[j][k] = max(goal2[j][k],goal1[j][k]);
}
int c = str[i] - 'a';
if(wa[trie[j][c]]) continue;
int temp,val;
temp = k|flag[trie[j][c]];
val = o[trie[j][c]];
if(dp2[trie[j][c]][temp] > dp1[j][k])
{
dp2[trie[j][c]][temp] = dp1[j][k];
goal2[trie[j][c]][temp] = goal1[j][k] + val;
}
else if(dp2[trie[j][c]][temp] == dp1[j][k])
{
goal2[trie[j][c]][temp] = max(goal2[trie[j][c]][temp],goal1[j][k] + val);
}
}
}
for(j = 0; j <= t; j ++)
{
for(k = 0; k < (1<<num); k ++)
{
dp1[j][k] = dp2[j][k];
dp2[j][k] = INF;
goal1[j][k] = goal2[j][k];
goal2[j][k] = -INF;
}
}
}
int ans1 = INF,ans2 = -INF;
for(i = 0; i < t; i ++)
{
if(ans1 > dp1[i][(1<<num)-1])
{
ans1 = dp1[i][(1<<num)-1];
ans2 = goal1[i][(1<<num)-1];
}
else if(ans1 == dp1[i][(1<<num)-1]&&ans2 < goal1[i][(1<<num)-1])
{
ans2 = goal1[i][(1<<num)-1];
}
}
if(ans1 >= INF)
printf("Case %d: Banned\n",cas++);
else
printf("Case %d: %d %d\n",cas++,ans1,ans2);
}
return 0;
}
/*
9
3
abdc 2
bd 3
c 4
abdc
3
aba 999
a 6
ab 5
aba
3
3
ab -1
bc -2
d -3
abcd
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: