100道动态规划——29 UVALive 5766 GRE Words AC自动机上的动态规划

来源:互联网 发布:udid授权软件 编辑:程序博客网 时间:2024/06/06 12:27

        之前怎么写都是WA,空了一天写还是WA,把cin和cout都换成scanf和printf就过,奇怪的问题

        定义状态dp[i]表示选择第i个串的最大价值

        状态转移方程就是 dp[i]=max{dp[j]}+value[i],其中要求0<=j<i,且串j是串i的子串

        因此问题就归结于高效判断子串的问题,这要求我们把每一个串都保存下来,当然,你记录每个点的father也行

        然后每次对于串i,就在AC自动机上扫它的子串

        代码里rec[i]表示第i个串的最后一个字符在AC自动机上的节点位置

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int maxm=3E5+5;int times,ans,kcase,sz,root,n,ch[maxm][26],fail[maxm],last[maxm],dp[maxm],v[maxm],rec[20005],val[20005],pos[20005],newnode();char str[maxm];void getfail(),ins(int k),init();int main(){//    ios_base::sync_with_stdio(false);    scanf("%d",×);    while(times--){        scanf("%d",&n);        //cin>>n;        init();        for(int i=0;i<n;++i){            scanf("%s%d",str+pos[i],&val[i]);            pos[i+1]=pos[i]+strlen(str+pos[i]);            //cin>>str[i];            ins(i);            //cin>>val[i];        }        getfail();        for(int i=0,u=root,p;i<n;++i,u=root)        if(val[i]>0){            for(int j=pos[i];j<pos[i+1];++j){                p=u=ch[u][str[j]];                if(!v[p]&&last[p]!=root)                    p=last[p];                while(v[p]){                    dp[rec[i]]=max(dp[rec[i]],dp[p]);                    p=last[p];                }            }            dp[rec[i]]+=val[i];            ans=max(ans,dp[rec[i]]);        }//        for(int i=0;i<n;++i)//            cout<<dp[rec[i]]<<' ';        printf("Case #%d: %d\n",++kcase,ans);//        cout<<"Case #"<<++kcase<<": "<<ans<<endl;    }    return 0;}void init(){    sz=ans=0;    root=newnode();}void ins(int k){    int u=root;    for(int i=pos[k];str[i];++i){        str[i]-='a';        if(ch[u][str[i]]==root)            ch[u][str[i]]=newnode();        u=ch[u][str[i]];    }    v[u]=1;    rec[k]=u;}void getfail(){    queue<int> q;    for(int i=0;i<26;++i)    if(ch[root][i]!=root){        q.push(ch[root][i]);        fail[ch[root][i]]=last[ch[root][i]]=root;    }    int u;    while(!q.empty()){        u=q.front();q.pop();        for(int i=0;i<26;++i)        if(ch[u][i]==root)            ch[u][i]=ch[fail[u]][i];        else{            fail[ch[u][i]]=ch[fail[u]][i];            last[ch[u][i]]=(v[fail[ch[u][i]]]?fail[ch[u][i]]:last[fail[ch[u][i]]]);            q.push(ch[u][i]);        }    }}int newnode(){    dp[sz]=v[sz]=0;    memset(ch[sz],0,sizeof ch[sz]);    return sz++;}


0 0
原创粉丝点击