100道动态规划——30 UVAlive 3907 Puzzle AC自动机上的动态规划,记忆化搜索

来源:互联网 发布:dior fix it 编辑:程序博客网 时间:2024/05/24 03:38

        一开始确实没有想到怎么做。。

        定义状态dp[i]表示自动机上的节点i还能够附加多长的字符,因此每一个串的结尾字符在自动机上对应的dp为0,这就是初始条件

        状态转移方程就是dp[i]=max{dp[j]}+1,其中j表示i点可达的节点,最后的答案就是dp[root]

       输出No的情况有两个,一个是在记忆化搜索的过程中,走到了一个已经访问过的节点了,此时有环,长度为无穷。还有一个就是答案为空串的情况

       标记访问过了用一个vis数组就好,用一个flag标记记录是否有环


#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int maxm=5E4+5;int times,n,sz,root,s,ch[maxm][26],fail[maxm],dp[maxm],rec[maxm],newnode();bool vis[maxm],val[maxm],flag;char str[55];void init();void ins(int k);void getfail();void dfs(int node);int main(){    scanf("%d",×);    while(times--){        init();        scanf("%d%d",&n,&s);        for(int i=0;i<s;++i){            scanf("%s",str);            ins(i);        }        getfail();        dfs(root);        if(flag||!dp[ch[root][rec[root]]])            printf("No\n");        else{            int u=root;            while(dp[ch[u][rec[u]]]){                printf("%c",rec[u]+'A');                u=ch[u][rec[u]];            }            printf("\n");        }    }    return 0;}void dfs(int node){    if(vis[node]&&dp[node]==-1){        flag=true;    }    else if(!vis[node]){        vis[node]=true;        int te=0;        for(int i=0;i<n;++i){            dfs(ch[node][i]);            if(flag)                return;            if(te<=dp[ch[node][i]])                te=dp[ch[node][i]],rec[node]=i;        }        dp[node]=te+1;    }}void init(){    sz=flag=0;    root=newnode();}int newnode(){    dp[sz]=-1;    vis[sz]=rec[sz]=val[sz]=0;    memset(ch[sz],0,sizeof ch[sz]);    return sz++;}void ins(int k){    int u=root;    for(int i=0;str[i];++i){        str[i]-='A';        if(ch[u][str[i]]==root)            ch[u][str[i]]=newnode();        u=ch[u][str[i]];    }    val[u]=vis[u]=1;    dp[u]=0;}void getfail(){    queue<int> q;    fail[root]=root;    for(int i=0;i<n;++i)    if(ch[root][i]!=root){        fail[ch[root][i]]=root;        q.push(ch[root][i]);    }    int u;    while(!q.empty()){        u=q.front();q.pop();        for(int i=0;i<n;++i){            if(ch[u][i]==root)                ch[u][i]=ch[fail[u]][i];            else{                fail[ch[u][i]]=ch[fail[u]][i];                q.push(ch[u][i]);            }        }    }}


0 0