hdu 2296 AC自动机+dp+路径记录

来源:互联网 发布:单位换算软件下载 编辑:程序博客网 时间:2024/05/19 12:12

Ring

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <vector>#include <queue>using namespace std;#define pb push_back#define INF (1<<30)struct node{    int son[26],fail;    int cnt;    char key;    node(){memset(son,0,sizeof(son));fail=0;cnt=0;}    node(char k):key(k){memset(son,0,sizeof(son));fail=0;cnt=0;}};vector<node> ac;int hash[256];int dp[51][2000];int n,m,T;string key[51][2000];//我采取了暴力做法,记录每条路径上的全部字符.另外一种做法是将字符串颠倒,只记录前驱.void init() {    for(int i=0;i<26;++i) hash['a'+i]=i;}void insert(const char *str,int num) {    int p=0,i=0;    while(str[p]) {        if(!ac[i].son[hash[str[p]]]) {            ac[i].son[hash[str[p]]]=ac.size();            ac.pb(node(str[p]));        }        i=ac[i].son[hash[str[p]]];        ++p;    }    ac[i].cnt=num;}void getFail() {    queue<int> qu;    qu.push(0);    while(!qu.empty()) {        int cur=qu.front();qu.pop();        for(int i=0;i<26;++i) {            int nex=ac[cur].son[i];            int p=ac[cur].fail;            if(nex) {//以下这部分实际上提供了另一种求fail的方法                qu.push(nex);                if(~p) ac[nex].fail=ac[p].son[i],ac[nex].cnt+=ac[ac[p].son[i]].cnt;                else ac[nex].fail=0;            }            else {//新的fail求法的关键是这一步,它保证每个儿子指针都指向某个节点                if(~p) ac[cur].son[i]=ac[p].son[i];//空儿子不是指向根,就是指向实儿子            }        }    }}char str[101][20];int main() {    ios::sync_with_stdio(false);    init();    cin >> T;    while(T--) {        cin >> n >> m;        ac.clear();        ac.pb(node('a'));        ac[0].fail=-1;        for(int i=0;i<m;++i) cin >> str[i];        for(int i=0;i<m;++i) {            int val;            cin >> val;            insert(str[i],val);        }        getFail();        for(int i=0;i<=n;++i)            for(int j=0;j<ac.size();++j)                dp[i][j]=-1,key[i][j].resize(60,'z');        dp[0][0]=0;        key[0][0]="";        int ans=0,ansi=0,ansj=0;        for(int i=0;i<n;++i)            for(int j=0;j<ac.size();++j) {                if(dp[i][j]==-1) continue;                for(int p=0;p<26;++p) {                    int son=ac[j].son[p];                    if(dp[i+1][son]<dp[i][j]+ac[son].cnt                       ||(dp[i+1][son]==dp[i][j]+ac[son].cnt&&key[i+1][son]>key[i][j]+char('a'+p))) {                        dp[i+1][son]=dp[i][j]+ac[son].cnt;                        key[i+1][son]=key[i][j]+char('a'+p);                    }                    if(dp[i+1][son]>ans||(dp[i+1][son]==ans&&i+1==ansi&&key[i+1][son]<key[ansi][ansj])) {                        ans=dp[i+1][son];                        ansi=i+1;ansj=son;                    }                }            }        cout << key[ansi][ansj] << endl;    }    return 0;}


原创粉丝点击