zoukankan      html  css  js  c++  java
  • HDU2296 Ring(AC自动机 DP)

    dp[i][j]表示行走i步到达j的最大值,dps[i][j]表示对应的串

    状态转移方程如下:

    dp[i][chi[j][k]] = min(dp[i - 1][j] + sum[chi[j][k]])

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<queue>
    using namespace std;
    
    #define hash(x) x-'a';
    const int N = 20000, CH = 26, INF = 0x3F3F3F3F;
    int n, m;
    struct Trie{
        Trie *next[CH];
        Trie *fail;
        int id;
    }tree[N];
    string dps[60][2008];
    string ans;
    
    //dp[i][j]表示行走i步到达j的最大值,dps[i][j]表示对应的串
    int dp[60][2008];
    int chi[1008][CH];
    int sum[1008];
    
    //先选长度短的,再按字典序选
    inline string min(string &a, string &b){
        if(a.size() != b.size()){
            return a.size() < b.size()? a :b;
        }
        return a < b? a :b;
    }
    class AC_Auto{
            int size;
            Trie *root;
            int mx;
    
        public:
        AC_Auto(){
            root = &tree[0];
            size=0;
            memset(&tree[0], 0, sizeof(Trie));
        }
    
        void insert(char *s, int si){
            Trie *p = root;
            for(int i = 0; s[i]; i++){
                int c = hash(s[i]);
                if(!p -> next[c]){
                    memset(&tree[++size], 0, sizeof(Trie));
                    p -> next[c] = &tree[size];
                    p -> next[c] ->id = size;
                }
                p = p -> next[c];
            }
            sum[p -> id] = si;
        }
    
        void build(){
            queue<Trie *> q;
            q.push(root);
            root -> fail = NULL;
            while(!q.empty()){
                Trie *now = q.front();
                q.pop();
                if(now -> fail){
                    //累加求串包含的子串价值和
                    sum[now -> id] += sum[now -> fail -> id];
                }
                for(int i = 0; i < CH; i++){
                    Trie *son = now -> next[i];
                    Trie *tp = (now == root)? root: now -> fail->next[i];
                    if(son == NULL){
                        now -> next[i] = tp;
                    }else{
                        son -> fail = tp;
                        q.push(son);
                    }
                    son = now -> next[i];
                    chi[now -> id][i] = son->id;
                }
            }
        }
        void solve(){
            mx = 0;
            ans.clear();
            for(int i = 0; i <= n; i++){
                for(int j = 0; j <= size; j++){
                    dp[i][j] = -INF;
                    dps[i][j].clear();
                }
            }
            dp[0][0] = 0;
            //枚举步骤,再枚举节点,状态转移
            for(int i = 1; i <= n; i++){
                for(int j = 0; j <= size; j++){
                    if(dp[i - 1][j] < 0){
                        continue;
                    }
                    for(int k = 0; k < CH; k++){
                        if(dp[i][chi[j][k]] < dp[i - 1][j] + sum[chi[j][k]]){
                            dp[i][chi[j][k]] = dp[i - 1][j] + sum[chi[j][k]];
    
                            dps[i][chi[j][k]] = dps[i - 1][j] + (char)(k + 'a');
    
                        }else if(dp[i][chi[j][k]] == dp[i - 1][j] + sum[chi[j][k]]){
                            dps[i][chi[j][k]] = min(dps[i - 1][j] + (char)(k + 'a'), dps[i][chi[j][k]]);
                        }
    
                        if(mx < dp[i][chi[j][k]]){
                            mx = dp[i][chi[j][k]];
                            ans = dps[i][chi[j][k]];
                        }else if(mx == dp[i][chi[j][k]]){
                            ans = min(ans, dps[i][chi[j][k]]);
                        }
                    }
                }
    
            }
            if(ans.size() > 0){
                cout<<ans<<"
    ";
            }else{
    
                cout<<"
    ";
            }
    
        }
    };
    
    char str[1008][1008];
    int main(){
        int t;
        cin>>t;
        while(t--){
            AC_Auto ac;
            cin>>n>>m;
            memset(sum, 0 ,  sizeof(sum));
    
            for(int i = 0; i < m; i++){
                scanf("%s", str[i]);
            }
            for(int i = 0; i < m ; i++){
                int val;
                scanf("%d", &val);
                ac.insert(str[i], val);
            }
            ac.build();
            ac.solve();
        }
        return 0;
    }
    

      

  • 相关阅读:
    mysql 查询优化
    图解Java常用数据结构(一)
    mybatis 详解(五)------动态SQL
    Mybatis的ResultMap的使用
    java系统变慢的优化简略步骤
    mysql基本操作
    mysql数据库的优化 一
    tomcat的启动启动与关闭
    vueJs的简单入门以及基础语法
    Oracle常用命令-用户、表空间、赋权限、导入导出
  • 原文地址:https://www.cnblogs.com/IMGavin/p/5813298.html
Copyright © 2011-2022 走看看