zoukankan      html  css  js  c++  java
  • Codeforces Round #362(Div1) D Legen...(AC自动机+矩阵快速幂)

    题目大意:

    给定一些开心串,每个串有一个开心值,构造一个串,每包含一次开心串就会获得一个开心值,求最大获得多少开心值。

    题解:

    首先先建立AC自动机。(建立fail指针的时候,对val要进行累加)

    然后在AC自动机上跑dp

    dp[i][j] = max(dp[i][j], dp[i-1][k] + v[j])

    写成矩阵形式就是(Mat[i][j]表示从i到j最大获得的开心值)

    C[i][j] = max(C[i][j], A[i][k]+B[k][j])

    然后这个形式也可以用快速幂的形式加速!!

    然后救过了!

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    using namespace std;
    const int N = 205, maxc = 27;
    char str[205];
    struct Trie{
        int Next[N][maxc], fail[N], tag[N];
        long long val[N];
        int root, L;
        int newnode(){
            for(int i = 0; i < maxc; i++)
                Next[L][i] = -1;
            tag[L++] = 0;
            return L-1;
        }
        void init() { L = 0; root = newnode(); }
        void Insert(char* s, int len, int v){
            int u = root;
            for(int i = 0; i < len; i++){
                int c = s[i] - 'a';
                if(Next[u][c] == -1) Next[u][c] = newnode();
                u = Next[u][c];
            }
            tag[u] = 1;
            val[u] += v;
        }
        void build(){
            queue<int> Q;
            fail[root] = root;
            for(int i = 0; i < maxc; i++){
                if(Next[root][i] == -1) Next[root][i] = root;
                else {
                    fail[Next[root][i]] = root;
                    Q.push(Next[root][i]);
                }
            }
            while(!Q.empty()){
                int u = Q.front();
                Q.pop();
                val[u] += val[fail[u]];
                for(int i = 0; i < maxc; i++){
                    int &v = Next[u][i];
                    if(v == -1){
                        v = Next[fail[u]][i];
                    } else {
                        Q.push(v);
                        fail[v] = Next[fail[u]][i];
                    }
                }
            }
        }
    }ac;
    
    struct Matrix{
        long long Mat[201][201];
        int n;
        Matrix() {n = 0; memset(Mat, 0, sizeof(Mat));}
        Matrix(Matrix &B){
            n = B.n;
            for(int i = 0; i <= n; i++)
                for(int j = 0; j <= n; j++)
                    Mat[i][j] = B.Mat[i][j];
        }
        Matrix operator +(const Matrix &B)const {
            Matrix C;
            C.n = n;
            for(int i = 0; i <= n; i++)
            for(int j = 0; j <= n; j++){
                C.Mat[i][j] = -1e18;
                for(int k = 0; k <= n; k++)
                    C.Mat[i][j] = max(C.Mat[i][j], Mat[i][k] + B.Mat[k][j]);
            }
            return C;
        }
        void print(){
            cout<<"*"<<endl;
            for(int i = 0; i <= n; i++){
                for(int j = 0; j <= n; j++) cout<<Mat[i][j]<<" ";
                cout<<endl;
            }
        }
    }A;
    Matrix mypow(Matrix A, long long b)
    { Matrix ans = A; b--; for(; b; b >>= 1, A = A+A) if(b&1) ans = ans+A; return ans;}
    int n, val[205];
    long long l;
    int main()
    {
        ac.init();
        cin>>n>>l;
        for(int i = 1; i <= n; i++) scanf("%d", &val[i]);
        for(int i = 1; i <= n; i++){
            cin>>str;
            ac.Insert(str, strlen(str), val[i]);
        }
        ac.build();
        A.n = ac.L-1;
        for(int i = 0; i < ac.L; i++)
            for(int j = 0; j < ac.L; j++)
                A.Mat[i][j] = -1e18;
        for(int i = 0; i < ac.L; i++){
            for(int j = 0; j < maxc; j++){
                int v = ac.Next[i][j];
                if(v == -1) continue;
                A.Mat[i][v] = ac.val[v];
            }
        }
        A = mypow(A, l);
        long long ans = -1e18;
        for(int i = 0; i < ac.L; i++) ans = max(ans, A.Mat[0][i]);
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    牛客练习赛81 B. 小 Q 与彼岸花(DP/Trie/树状数组/FWT/好题)
    HDU6570 Wave(DP)
    HDU6567 Cotree(树的重心/树形DP)
    P1712 [NOI2016] 区间(双指针/线段树)
    P1063 [NOIP2006 提高组] 能量项链(区间DP)
    Jquery
    Jquery
    Jquery
    Jquery 学习
    JS学习
  • 原文地址:https://www.cnblogs.com/Saurus/p/7706626.html
Copyright © 2011-2022 走看看