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;
}

  

原文地址:https://www.cnblogs.com/liulangye/p/2999262.html