• CF1163D Mysterious Code(AC自动机+dp)


    本题观察数据量非常小,并且求的是多串匹配,因此可以考虑使用ac自动机

    设计dp状态为f[][],表示c中前i个字符匹配到第j个节点所能达到的最大值。

    首先我们知道,两个匹配串在结束位置的点分别是+-1,而所有前缀能包含这两个字符串的,也应该设为对应的数值,对fail树进行修改进行。

    dp的时候,枚举位置,枚举之前处于的节点位置,当前位置是什么字符,进行dp即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5e5+10;
    struct node{
        int cnt;
        node * nxt[27];
        node * fail;
        vector<node *> num;
    }*rt;
    node pool[N];
    int n,idx;
    int val[N];
    int num;
    int f[1100][200];
    void insert(string s,int x){
        node *p=rt;
        int i;
        for(i=0;i<s.size();i++){
            int sign=s[i]-'a';
            if(p->nxt[sign]==NULL){
                p->nxt[sign]=pool+(++idx);
                p->nxt[sign]->cnt=++num;
            }
            p=p->nxt[sign];
            if(i==(int)s.size()-1){
                val[p->cnt]=x;
            }
        }
    }
    void build(){
        int i;
        queue<node *> q;
        rt->fail=rt;
        for(i=0;i<26;i++){
            if(rt->nxt[i]){
                rt->nxt[i]->fail=rt;
                rt->num.push_back(rt->nxt[i]);
                q.push(rt->nxt[i]);
            }
            else{
                rt->nxt[i]=rt;
                rt->nxt[i]->fail=rt;
            }
        }
        while(q.size()){
            auto t=q.front();
            q.pop();
            for(i=0;i<26;i++){
                if(t->nxt[i]){
                    t->nxt[i]->fail=t->fail->nxt[i];
                    t->fail->nxt[i]->num.push_back(t->nxt[i]);
                    q.push(t->nxt[i]);
                }
                else{
                    t->nxt[i]=t->fail->nxt[i];
                }
            }
            val[t->cnt]+=val[t->fail->cnt];
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        int i;
        rt=pool;
        rt->cnt=0;
        string c;
        cin>>c;
        n=c.size();
        c=" "+c;
        string s,t;
        cin>>s>>t;
        insert(s,1);
        insert(t,-1);
        build();
        memset(f,-0x3f,sizeof f);
        f[0][0]=0;
        for(i=1;i<=n;i++){
            for(int j=0;j<=num;j++){
                for(int k=0;k<26;k++){
                    if(c[i]=='*'||(c[i]=='a'+k)){
                        int id=(pool+j)->nxt[k]->cnt;
                        f[i][id]=max(f[i][id],f[i-1][j]+val[id]);
                    }
                }
            }
        }
        int ans=-0x3f3f3f3f;
        for(i=0;i<=num;i++)
            ans=max(ans,f[n][i]);
        cout<<ans<<endl;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    各位相加
    模板方法设计模式
    581. Shortest Unsorted Continuous Subarray
    LeetCode
    判断质数
    整除问题
    A+B+C问题
    juery 安全加固 集合
    丁洪波 -- 不要“ 总是拿着微不足道的成就来骗自己”
    avalon源码阅读(1)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13413562.html
Copyright © 2020-2023  润新知