hdu 4534 郑厂长系列故事——新闻净化

http://acm.hdu.edu.cn/showproblem.php?pid=4534

自动机+DP(状态压缩)

整体思路应该很明确,但要注意一些细节方面的处理 否则会wa

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<map>

#include<set>

#include<vector>

#include<stack>

#include<queue>



using namespace std;

const int MOD=1000000007;

const int N=110;

const int M=1610;

const int K=26;

struct nodeTrie

{

    int v;

    int k;

    int fail;

    int next[K];

    void initialize()

    {

        v=0;

        k=0;

        fail=-1;

        memset(next,-1,sizeof(next));

    }

}trie[M];

int cnt,root;

int to[M][K];

char s[K];

char words[N];

int dp1[2][M][1<<8],dp2[2][M][1<<8];

int getNewNode()

{

    ++cnt;

    trie[cnt].initialize();

    return cnt;

}

void addWord(int p,char *s,int k,int l)

{

    if(s[0]=='\0') return ;

    for(int i=0;s[i]!='\0';++i)

    {

        if(trie[p].next[s[i]-'a']==-1)

        trie[p].next[s[i]-'a']=getNewNode();

        p=trie[p].next[s[i]-'a'];

    }

    if(k==999)

    trie[p].k=(1<<(l-1));

    else if(k==-999)

    trie[p].k=-1;

    else

    trie[p].v=k;

}

int init(int n)

{

    cnt=-1;

    root=getNewNode();

    int l=0;

    while(n--)

    {

        int k;

        scanf("%s %d",s,&k);//puts(s);cout<<k<<endl;

        if(k==999) ++l;

        addWord(root,s,k,l);

    }

    return l;

}

void bfs(int p)

{

    trie[p].fail=root;

    queue<int>qt;

    qt.push(p);

    while(!qt.empty())

    {

        int y;

        int x=qt.front();qt.pop();

        for(int i=0;i<K;++i)

        if(trie[x].next[i]!=-1)

        {

            qt.push(trie[x].next[i]);

            if(x==root)

            {trie[trie[x].next[i]].fail=root;continue;}

            y=trie[x].fail;

            while(y!=root&&trie[y].next[i]==-1)

            y=trie[y].fail;

            if(trie[y].next[i]!=-1)

            trie[trie[x].next[i]].fail=trie[y].next[i];

            else

            trie[trie[x].next[i]].fail=root;

            int l=trie[x].next[i],r=trie[trie[x].next[i]].fail;

            if(trie[l].k==-1||trie[r].k==-1)

            trie[l].k=-1;

            else {trie[l].k=(trie[l].k|trie[r].k);trie[l].v+=trie[r].v;}

        }

    }

}

void makeTo(int n,int k)

{

    for(int i=0;i<=n;++i)

    for(int j=0;j<k;++j)

    {



        int p=i;

        while(p!=root&&trie[p].next[j]==-1)

        p=trie[p].fail;

        if(trie[p].next[j]!=-1)

        to[i][j]=trie[p].next[j];

        else

        to[i][j]=root;

    }

};

int main()

{

    //freopen("data.in","r",stdin);

    int T;

    scanf("%d",&T);

    for(int w=1;w<=T;++w)

    {

        int n;

        scanf("%d",&n);

        int h=(1<<init(n));

        bfs(root);

        makeTo(cnt,K);

        scanf("%s",words);

        int m=strlen(words);

        memset(dp1,0,sizeof(dp1));

        memset(dp2,0,sizeof(dp2));

        int M=0,P=0;

        for(int i=0;i<=m;++i)

        {

            for(int j=0;j<=cnt;++j)

            for(int l=0;l<h;++l)

            {dp1[(i+1)%2][j][l]=0;dp2[(i+1)%2][j][l]=0;}

            for(int j=0;j<=cnt;++j)

            for(int l=0;l<h;++l)

            {

                if(dp1[i%2][j][l]==0&&(j>0||l>0)) continue;

                if(l==(h-1))

                {

                    if(M<dp1[i%2][j][l]||(M==dp1[i%2][j][l]&&P<dp2[i%2][j][l]))

                    {M=dp1[i%2][j][l];P=dp2[i%2][j][l];}

                }

                if(i==m) continue;

                int r=to[j][words[i]-'a'];

                if(dp1[(i+1)%2][j][l]<dp1[i%2][j][l]||

                   (dp1[(i+1)%2][j][l]==dp1[i%2][j][l]&&dp2[(i+1)%2][j][l]<dp2[i%2][j][l]))

                    {dp1[(i+1)%2][j][l]=dp1[i%2][j][l];dp2[(i+1)%2][j][l]=dp2[i%2][j][l];}

                if(trie[r].k!=-1)

                {

                    int k=(l|(trie[r].k));

                    if(dp1[(i+1)%2][r][k]<dp1[i%2][j][l]+1||

                   (dp1[(i+1)%2][r][k]==dp1[i%2][j][l]+1&&dp2[(i+1)%2][r][k]<dp2[i%2][j][l]+trie[r].v))

                    {dp1[(i+1)%2][r][k]=dp1[i%2][j][l]+1;dp2[(i+1)%2][r][k]=dp2[i%2][j][l]+trie[r].v;}

                }

            }

        }

        printf("Case %d: ",w);

        if(M==0)

        printf("Banned\n");

        else

        printf("%d %d\n",m-M,P);

    }

    return 0;

}

  

你可能感兴趣的:(HDU)