码迷,mamicode.com
首页 > 其他好文 > 详细

CF1163D Mysterious Code(AC自动机+dp)

时间:2020-08-01 12:35:22      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:ack   sed   自动   ons   namespace   queue   pen   pool   因此   

本题观察数据量非常小,并且求的是多串匹配,因此可以考虑使用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

 

CF1163D Mysterious Code(AC自动机+dp)

标签:ack   sed   自动   ons   namespace   queue   pen   pool   因此   

原文地址:https://www.cnblogs.com/ctyakwf/p/13413562.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!