HDU 4534

AC自动机水题,想清楚状态表示即可。

我一开始多设计一维状态记录之前用了多少个删除操作,MLE,其实这个状态不需要记录的,作为一个待求最值的变量。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 1700
using namespace std;
const int INF=-((~(0U))>>1);
char s[110];
int score;
int next[N][26],pos,flag[N],sta[N],val[N],fail[N],tot;

int newnode(){
    memset(next[pos],0,sizeof(next[pos]));
    flag[pos]=fail[pos]=sta[pos]=val[pos]=0;
    return pos++;
}

void insert(char * s,int score){
    int p=0,i;
    for(i=0;s[i];i++){
        int k=s[i]-'a';
        p=next[p][k]?next[p][k]:next[p][k]=newnode();
    }
    if(score==999){
        flag[p]=1;
        sta[p]=(1<<tot);
        tot++;
    }
    else if(score==-999){
        flag[p]=-1;
    }
    else{
        flag[p]=2;
        val[p]=score;
    }
}

void makefail(){
    queue<int>q;
    q.push(0);
    int i,p=0;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(i=0;i<26;i++){
            int v=next[u][i];
            if(v==0) next[u][i]=next[fail[u]][i];
            else q.push(v);
            if(u&&v){
                fail[v]=next[fail[u]][i];
                if(flag[fail[v]]==-1){
                    flag[v]=-1;
                }
                else if(flag[v]!=-1){
                    sta[v]|=sta[fail[v]];
                    val[v]+=val[fail[v]];
                }
            }
        }
    }
}

int dp[2][260][N];
int cost[2][260][N];
void makeans(){
    int i,j,k,len,cur;
    len=strlen(s);
    cur=1;
    for(j=0;j<(1<<tot);j++)
        for(k=0;k<pos;k++)
            dp[0][j][k]=-INF,cost[0][j][k]=INF;
    dp[0][0][0]=0;
    cost[0][0][0]=0;
    for(i=0;s[i];i++){
        for(j=0;j<(1<<tot);j++)
            for(k=0;k<pos;k++)
                dp[cur][j][k]=-INF,cost[cur][j][k]=INF;
        for(j=0;j<(1<<tot);j++){
            for(k=0;k<pos;k++){
                if(dp[cur^1][j][k]==-INF)continue;
                if(dp[cur][j][k]>dp[cur^1][j][k]+1){
                    dp[cur][j][k]=dp[cur^1][j][k]+1;
                    cost[cur][j][k]=cost[cur^1][j][k];
                }
                else if(dp[cur][j][k]==dp[cur^1][j][k]+1){
                    cost[cur][j][k]=max(cost[cur][j][k],cost[cur^1][j][k]);
                }
            }
        }
        for(j=0;j<(1<<tot);j++){
            for(k=0;k<pos;k++){
                if(dp[cur^1][j][k]==-INF)continue;
                int v=next[k][s[i]-'a'];
                if(flag[v]==-1)continue;
                //if((j|sta[v])==((1<<tot)-1)) printf("***%d %d %d %d\n",i,j,k,p);
                if(dp[cur][j|sta[v]][v]>dp[cur^1][j][k]){
                    dp[cur][j|sta[v]][v]=dp[cur^1][j][k];
                    cost[cur][j|sta[v]][v]=cost[cur^1][j][k]+val[v];
                }
                else if(dp[cur][j|sta[v]][v]==dp[cur^1][j][k]){
                    cost[cur][j|sta[v]][v]=max(cost[cur][j|sta[v]][v],cost[cur^1][j][k]+val[v]);
                }
            }
        }
        cur^=1;
    }
    int ans1=-INF;
    int ans=INF;
    for(j=0;j<pos;j++){
        if(dp[cur^1][(1<<tot)-1][j]<ans1){
            ans1=dp[cur^1][(1<<tot)-1][j];
            ans=cost[cur^1][(1<<tot)-1][j];
        }
        else if(dp[cur^1][(1<<tot)-1][j]==ans1){
            ans=max(ans,cost[cur^1][(1<<tot)-1][j]);
        }
    }
    if(ans1!=-INF){
        printf("%d %d\n",ans1,ans);
        return ;
    }
    printf("Banned\n");
}

int main(){
    int t,T,n,i,j;
    scanf("%d",&T);
    for(t=1;t<=T;t++){
        scanf("%d",&n);
        pos=0,newnode();
        tot=0;
        for(i=1;i<=n;i++){
            scanf("%s %d",s,&score);
            insert(s,score);
        }
        makefail();
        scanf("%s",s);
        printf("Case %d: ",t);
        makeans();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值