HDU 4057 AC自动机+状态压缩DP

ZOJ 3545也是这个题。

每个节点的flag表示经过状态压缩的当前节点包含的所有字串。

在build的时候直接通过  flag = flag or fail->flag 来更新

f[i][j][k]表示长度为i时位于第j个节点包含字串状态为k是否可能

因为空间限制,利用滚动数组,注意初始化问题

转移的时候  if (f[i][j][k]) f[i+1][son][k|son->flag] =true; 

初始化 f[0][0][0]=true  后顺推即可。

 

对于每一个状态,预处理出该状态的值。

见 void prework(); 函数

H[i] = H[i-lowbit(i)]+H[lowbit(i)];

 

最后对所有可达状态取最大值即可。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define rep(i,a,b) for(int i=a;i<b;i++)
const int MAXC = 4;
const int MAXN = 1010;

inline int lx(char c){
    if (c=='A') return 0;
    if (c=='T') return 1;
    if (c=='C') return 2;
    return 3;
}

struct Tnode{
    Tnode *ch[MAXC];
    Tnode *f;
    int flag;
    void reset(){
        memset(ch,0,sizeof(ch));
        f = NULL;
        flag =0;
    }
} *init;
Tnode pool[MAXN];
int cnt;

void insert(char *s,int qq){
    Tnode *now = init;
    while(*s){
        int p = lx(*s++);
        if (!now->ch[p]){
            now->ch[p]=&pool[++cnt];
            pool[cnt].reset();
        }
        now = now->ch[p];
    }
    now->flag=now->flag|qq;
}

queue <Tnode*> q;
void build(){
    q.push(init);
    while(!q.empty()){
        Tnode *now = q.front();
        q.pop();
        rep(i,0,MAXC){
            if (now->ch[i]){
                Tnode *p=now->f;
                while(p && !p->ch[i]) p=p->f;
                now->ch[i]->f = p?p->ch[i]:init;
                q.push(now->ch[i]);
            }
        }
    }

    init->f=init;
    rep(i,0,MAXC)
        if (init->ch[i]) q.push(init->ch[i]);
            else init->ch[i]=init;
    while(!q.empty()){
        Tnode *now = q.front();
        now->flag = now->flag | now->f->flag;
        q.pop();
        rep(i,0,MAXC)
            if (now->ch[i]) q.push(now->ch[i]);
                else now->ch[i]=now->f->ch[i];
    }
}

int Q[15];
bool f[2][MAXN][1024];
int N,L;
char s[110];
bool ans[1024];
int H[1024];

void dp(){
    memset(ans,0,sizeof(ans));
    int p1=0;
    int p2=1;
    memset(f[p1],0,sizeof(f[p1]));
    f[0][0][0]=true;
    rep(l,0,L){
        memset(f[p2],0,sizeof(f[p2]));
        rep(i,0,cnt+1){
            rep(k,0,1<<N){
                if (!f[p1][i][k]) continue;
                rep(c,0,MAXC){
                    f[p2][pool[i].ch[c]-pool][k|pool[i].ch[c]->flag]=true;
                }
            }
        }
        swap(p1,p2);
    }
    rep(i,0,cnt+1) rep(j,0,1<<N)
        if (f[p1][i][j]) ans[j]=true;
}

inline int lowbit(int p){
    return p&-p;
}

void prework(){
    memset(H,0,sizeof(H));
    H[0]=0;
    rep(i,0,N) H[1<<i]=Q[i];
    rep(i,1,1<<N) H[i]=H[i-lowbit(i)]+H[lowbit(i)];
}

int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d%d\n",&N,&L)!=EOF){
        init = &pool[0];
        cnt=0;
        pool[0].reset();
        rep(i,0,N){
            scanf("%s",s);
            scanf("%d\n",&Q[i]);
            insert(s,1<<i);
        }
        build();
        prework();
        dp();
        int rul = -1;
        rep(i,0,1<<N) if (ans[i]) rul = max(rul,H[i]);
        if (rul<0) printf("No Rabbit after 2012!\n"); else printf("%d\n",rul);
    }
}
View Code

 

posted @ 2013-10-15 14:16  qinhang3  阅读(201)  评论(0编辑  收藏  举报