您的位置:首页 > 其它

【AC自动机+DP】 HDOJ 4534 郑厂长系列故事——新闻净化

2014-10-01 21:16 218 查看
dp[i][j][k]代表走过i个字符,在AC自动机上走了j步,达到了k的状态(状态压缩),的最大利益。。。然后转移一下即可。。

#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 2005
#define maxm 40005
//#define eps 1e-10
#define mod 10000007
#define INF 1e9
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
void scanf(int &__x){__x=0;char __ch=getchar();while(__ch==' '||__ch=='\n')__ch=getchar();while(__ch>='0'&&__ch<='9')__x=__x*10+__ch-'0',__ch = getchar();}
LL gcd(LL _a, LL _b){if(!_b) return _a;else return gcd(_b, _a%_b);}
//head

struct AC
{
int next[maxn][26];
int fail[maxn];
int cost[maxn];
int end[maxn];
int no[maxn];
char s[maxn];
queue<int> q;
int top, now, root;

int newnode(void)
{
end[top] = cost[top] = no[top] = 0, fail[top] = -1;
for(int i = 0; i < 26; i++) next[top][i] = -1;
return top++;
}

void init(void)
{
top = 0;
root = newnode();
}

void insert(int x, int c)
{
int len = strlen(s);
now = root;
for(int i = 0; i < len; i++) {
int t = s[i] - 'a';
if(next[now][t] == -1) next[now][t] = newnode();
now = next[now][t];
}
if(x == -1 && c == -1) no[now] = 1;
else end[now] = x, cost[now] = c;
}

void build(void)
{
now = root;
for(int i = 0; i < 26; i++)
if(next[now][i] == -1) next[now][i] = root;
else {
fail[next[now][i]] = root;
q.push(next[now][i]);
}
while(!q.empty()) {
now = q.front(), q.pop();
no[now] |= no[fail[now]];
end[now] |= end[fail[now]];
cost[now] += cost[fail[now]];
for(int i = 0; i < 26; i++)
if(next[now][i] == -1) next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
q.push(next[now][i]);
}
}
}
};

const int inf = -500000;
int dp[2][1605][300];
int res[2][1605][300];
char s[maxn];
int n, kk, m, tt;
AC ac;

void read(void)
{
int x;
kk = 0;
scanf("%d", &m);
ac.init();
for(int i = 0; i < m; i++) {
scanf("%s", ac.s);
scanf("%d", &x);
if(x == 999) ac.insert(1 << kk, 0), kk++;
else if(x == -999) ac.insert(-1, -1);
else ac.insert(0, x);
}
ac.build();
scanf("%s", s);
n = strlen(s);
}

void init(void)
{
tt = 1 << kk;
for(int i = 0; i < 2; i++)
for(int j = 0; j < ac.top; j++)
for(int k = 0; k < tt; k++)
dp[i][j][k] = -INF;
}

void work(void)
{
int now = 0;
dp[0][0][0] = 0;
for(int i = 0; i < n; i++) {
int t = s[i] - 'a';
for(int j = 0; j < ac.top; j++)
for(int k = 0; k < tt; k++) {
if(dp[now][j][k] == -INF) continue;
dp[now^1][j][k] = max(dp[now^1][j][k], dp[now][j][k] + inf);
int t1 = ac.next[j][t], t2 = k | ac.end[t1];
if(!ac.no[t1]) dp[now^1][t1][t2] = max(dp[now^1][t1][t2], dp[now][j][k] + ac.cost[t1]);
}
for(int j = 0; j < ac.top; j++)
for(int k = 0; k < tt; k++)
dp[now][j][k] = -INF;
now ^= 1;
}
int ans = -INF, res, t = tt-1;
for(int i = 0; i < ac.top; i++) ans = max(ans, dp[now][i][t]);
if(ans == -INF) printf("Banned\n");
else {
res = ans / inf;
ans -= res * inf;
if(ans < inf / 2) ans -= inf, res++;
printf("%d %d\n", res, ans);
}
}

int main(void)
{
int _, __;
while(scanf("%d", &_)!=EOF) {
__ = 0;
while(_--) {
read();
init();
printf("Case %d: ", ++__);
work();
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: