ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

fzyjojP2963 -- [校内训练20161227]疫情控制问题

2019-02-03 18:39:25  阅读:212  来源: 互联网

标签:cnt ch 校内 SAM int ll 20161227 fzyjojP2963 define


(题干中的废话已经划去)

 

dp显而易见

收益为负数的可以直接扔掉不管。不要一定更优

子串问题,考虑SAM

建立广义SAM

尝试匹配,匹配到的位置的parent树祖先如果有完整的串,那么可以从这个串转移

考虑祖先不好考虑

不妨考虑i对j(i<j)的贡献,就是子树了

线段树维护dfn序,区间对val取max

 

SAM学傻了

这个,由于是"完整出现”,所以AC自动机就可以(比广义SAM好写好调)

走一走属于第j个串的路径,对应的fail树的祖先包含i(i<j)的结束位置,那么可以转移

所以,同理,走完i之后,整个fail树子树的dp值和val取max

但是注意一点,根节点标号是0(反正我trie都这样写)

 

代码:

#include<bits/stdc++.h>
#define il inline
#define int long long
#define reg register int
#define mid ((l+r)>>1)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=300000+5;
int n,m;
struct node{
    int nxt,to;
}e[2*N];
int hd[N],cnt;
void add(int x,int y){
    e[++cnt].nxt=hd[x];
    e[cnt].to=y;
    hd[x]=cnt;
}
char s[N],b[N];
int len[N],st[N];
ll v[N],f[N];
int dfn[N],dfn2[N];
int df;
struct seg{
    ll mx;
    ll tag;
}t[4*N];
void pushup(int x){
    t[x].mx=max(t[x<<1].mx,t[x<<1|1].mx);
}
void pushdown(int x){
    if(t[x].tag<=0) return;
    t[x<<1].tag=max(t[x<<1].tag,t[x].tag);
    t[x<<1].mx=max(t[x<<1].mx,t[x].tag);
    
    t[x<<1|1].tag=max(t[x<<1|1].tag,t[x].tag);
    t[x<<1|1].mx=max(t[x<<1|1].mx,t[x].tag);
    t[x].tag=0;
}
void upda(int x,int l,int r,int L,int R,ll c){
    if(L<=l&&r<=R){
        t[x].mx=max(t[x].mx,c);
        t[x].tag=max(t[x].tag,c);
        return ;
    }
    pushdown(x);
    if(L<=mid) upda(x<<1,l,mid,L,R,c);
    if(mid<R) upda(x<<1|1,mid+1,r,L,R,c);
    pushup(x);
}
ll query(int x,int l,int r,int p){
    if(l==r){
        return t[x].mx;
    }
    pushdown(x);
    if(p<=mid) return query(x<<1,l,mid,p);
    else return query(x<<1|1,mid+1,r,p);
}
void cle(int x,int l,int r){
    t[x].mx=0;t[x].tag=0;
    if(l==r) return;
    cle(x<<1,l,mid);cle(x<<1|1,mid+1,r);
}
struct AC{
    int fail[N],ch[N][26];
    int cnt;
    void ins(char *s,int l){
        //int len=strlen(s+1);
        int now=0;
        for(reg i=1;i<=l;++i){
            int c=s[i]-'a';
            if(!ch[now][c]) ch[now][c]=++cnt;
            now=ch[now][c];
        }
    }
    void build(){
        queue<int>q;
        for(reg i=0;i<26;++i){
            if(ch[0][i]) fail[ch[0][i]]=0,q.push(ch[0][i]);
        }
        while(!q.empty()){
            int x=q.front();q.pop();
            for(reg i=0;i<26;++i){
                if(ch[x][i]){
                    fail[ch[x][i]]=ch[fail[x]][i];
                    q.push(ch[x][i]);
                }
                else ch[x][i]=ch[fail[x]][i];
            }
        }
        for(reg i=1;i<=cnt;++i){
            add(fail[i],i);
        }
    }
    void clear(){
        memset(fail,0,sizeof fail);
        cnt=0;
        memset(ch,0,sizeof ch);
    }
    void dfs(int x){
        dfn[x]=++df;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            dfs(y);
        }
        dfn2[x]=df;
    }
    ll wrk(char *s,int l,int id){
        ll ret=0;
        int now=0;
        for(reg i=1;i<=l;++i){
            int c=s[i]-'a';
            now=ch[now][c];
    //        cout<<"now "<<now<<" i "<<i<<" dfn "<<dfn[now]<<endl;
            ret=max(ret,query(1,1,df,dfn[now]));
        }
    //    cout<<dfn[now]<<".. "<<dfn2[now]<<endl;
        upda(1,1,df,dfn[now],dfn2[now],ret+v[id]);
        return ret;
    }
}ac;
void clear(){
    ac.clear();
    if(df)cle(1,1,df);
    df=0;cnt=0;
    n=0;
    memset(hd,0,sizeof hd);
    
}
int main(){
    //return 0;
    int t;
    rd(t);
    while(t--){
        clear();    
        rd(m);
        int tot=0;    
        for(reg i=1;i<=m;++i){
            scanf("%s",b+1);
            scanf("%lld",&v[i]);
            st[i]=tot+1;
            len[i]=strlen(b+1);
            for(reg j=tot+1;j<=tot+len[i];++j){
                s[j]=b[j-tot];
            }    
            tot=tot+len[i];
            ac.ins(b,len[i]);
        }
    //    cout<<" after ac.ins "<<endl;
        ac.build();
        ac.dfs(0);//find dfn
        ll ans=0;
    //    cout<<" let's wrk "<<endl;
        for(reg i=1;i<=m;++i){
    //        cout<<" ii "<<i<<"--------------------"<<v[i]<<" len "<<len[i]<<" st "<<st[i]<<endl;
            //if(v[i]<=0) continue;
            for(reg j=st[i];j<=st[i]+len[i]-1;++j){
                b[j-st[i]+1]=s[j];
            }
        //    cout<<b+1<<endl;
            f[i]=ac.wrk(b,len[i],i)+v[i];
        //    cout<<i<<" : "<<f[i]<<endl;
            ans=max(ans,f[i]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

}
signed main(){
    freopen("2963.in","r",stdin);
    freopen("2963.out","w",stdout);
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/2/3 11:36:24
*/

 

标签:cnt,ch,校内,SAM,int,ll,20161227,fzyjojP2963,define
来源: https://www.cnblogs.com/Miracevin/p/10350805.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有