zoukankan      html  css  js  c++  java
  • 洛谷P3401 [USACO12JAN]Video Game G(AC自动机+记忆化搜索)

    题目链接:https://www.luogu.com.cn/problem/P3041

    无关的话:最近在学AC自动机,感觉很多AC自动机和矩阵快速幂以及dp有关系。那些板子题其实对板子的要求还是很高的,我听说指针版AC自动机会快一些,奈何我不会指针,就自己瞎凑了一个板子出来。以前听学长说有些东西只有0次和N次,我今天第一次接触面向对象保存板子,发现真的好用。以后遇到数据机构我都用面向对象封装模板了。

    题解:

    1. 在AC自动机上如果一个点表示一个字符串以及它的后缀,则一个点可以对应多个combo技能(这是关键点)
    2. 可以先用拓扑排序处理出每个点对应了多少个combo技能,处理时要用fail的反向边即refail计算入度(这里应该不用这么麻烦,build的时候就可以直接加上去了)
    3. 然后就是记忆化搜索啦,这题没啥坑点。
    4. 我的板子tot最后需要减个1(因为实际上是每次我都预处理的)

    AC代码:

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    int n,k;
    int indeg[1005];
    vector<int> refail[1005];
    class ac_auto{
        public:
            const static int maxn=5e4+100;
            int tot,root;
            int tree[maxn][5]; 
            int num[maxn];
            int fail[maxn];
            int newnode(){
                for(int i=0;i<3;i++){
                    tree[tot][i]=0;
                }
                num[tot]=0;
                return tot++;
            }
            
            void init(){
                tot=0;
                root=newnode();
            }
                            
            void insert_(string s){
                int now = root;
                for(int i=0;i<s.length();i++){
                    int id=s[i]-'A';
                    if(!tree[now][id]){
                        tree[now][id]=newnode();
                    }
                    now=tree[now][id];
                }
                num[now]++;
            }
            
            void getFail(){
                queue <int>q;
                for(int i=0;i<3;i++){
                    if(tree[0][i]){
                        fail[tree[0][i]] = 0;
                        q.push(tree[0][i]);
                    }
                }
                while(!q.empty()){
                    int now = q.front();
                    q.pop();
                    for(int i=0;i<3;i++){
                        if(tree[now][i]){
                            fail[tree[now][i]] = tree[fail[now]][i];
                            refail[tree[fail[now]][i]].pb(tree[now][i]);
                            indeg[tree[now][i]]++;
                            q.push(tree[now][i]);
                        }
                        else
                            tree[now][i] = tree[fail[now]][i];
                    }
                }
            }    
            
    }acam;
    void toposort(){
        queue<int> q;
        for(int i=0;i<acam.tot;i++){
            if(!indeg[i]) q.push(i);
        }
        while(!q.empty()){
            int now=q.front();q.pop();
            for(auto v:refail[now]){
                acam.num[v]+=acam.num[now];
                if(--indeg[v]==0) q.push(v);
            }
        }
    }
    int dp[1010][410];
    int dfs(int pos,int now){
        if(pos>k) return 0;
        if(dp[pos][now]) return dp[pos][now];
        int ans=0;
        rep(i,0,2){
            ans=max(ans,acam.num[acam.tree[now][i]]+dfs(pos+1,acam.tree[now][i]));
        }
        return dp[pos][now]=ans;
    }
    int main(){
        cin>>n>>k;
        acam.init();
        rep(i,1,n){
            string s;cin>>s;
            acam.insert_(s);
        }
        acam.getFail();
        toposort();
        cout<<dfs(1,0)<<endl;
    }
    View Code
  • 相关阅读:
    计蒜客
    CodeForces -1216B.Shooting
    关于gets读入因为缓冲区出现的问题
    CodeForces
    Codeforces Round #603 (Div. 2) C.Everyone is A Winner!
    Codeforces Round #603 (Div. 2) A.Sweet Problem
    Codeforces Round #603 (Div. 2)B. PIN Codes
    Codeforces 524C.The Art of Dealing with ATM(暴力)
    Codeforces Round #600 (Div. 2) C. Sweets Eating
    数组的定义和初始化
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13434009.html
Copyright © 2011-2022 走看看