• hdu 4117 GRE Words AC自动机DP


    题目:给出n个串,问最多能够选出多少个串,使得前面是后面串的子串(按照输入顺序)

    分析:

      其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多。

      对于这题来说,需要离线操作。dp转移也是很显然。

      但是由于数据比较大,所以普通的沿着fail指针往上走,逐步更新答案会TLE。

      考虑把fail指针反向,由于ac自动机的每个节点均有唯一的fail指针,若是沿着fail指针往上走,显然都会走到root,所以反向之后显然是一棵树,不妨称之为fail树。fail树有什么特点呢?可以画个图试试,如果儿子节点出现过,那么他的祖先显然也会出现!

      因此,正确的做法时:

      建立所有单词的AC自动机,对于每个节点的转移,都是从parent[]或者从fail[],fail[fail[]],...得到的。可以看出fail[]的关系形成一棵树,于是问题转化成,不断在节点处插入,询问点到根路径上的最大值,可以利用dfs序列转化用线段树维护。

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <complex>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    #define RD(n) scanf("%d",&n)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
    #define All(vec) vec.begin(),vec.end()
    #define MP make_pair
    #define PII pair<int,int>
    #define PQ priority_queue
    #define cmax(x,y) x = max(x,y)
    #define cmin(x,y) x = min(x,y)
    #define Clear(x) memset(x,0,sizeof(x))
    #define lson rt<<1
    #define rson rt<<1|1
    #define SZ(x) x.size()
    
    /******** program ********************/
    
    const int MAXN = 3e5+5;
    const int kind = 26;
    
    char s[MAXN];
    int beg[MAXN];
    
    struct segTree {
        int l,r,mx;
        int cov;
        inline int mid() {
            return (l+r)>>1;
        }
    } tree[MAXN<<2];
    
    void build(int l,int r,int rt) {
        tree[rt].l = l;
        tree[rt].r = r;
        tree[rt].cov = tree[rt].mx = 0;
        if(l==r)return;
        int mid = tree[rt].mid();
        build(l,mid,lson);
        build(mid+1,r,rson);
    }
    
    void update(int rt){
        if(tree[rt].cov==0)return;
        cmax( tree[lson].cov,tree[rt].cov );
        cmax( tree[rson].cov,tree[rt].cov );
        cmax( tree[lson].mx,tree[rt].cov );
        cmax( tree[rson].mx,tree[rt].cov );
        tree[rt].cov = 0;
    }
    
    void modify(int l,int r,int mx,int rt) {
        if(l<=tree[rt].l&&tree[rt].r<=r) {
            cmax(tree[rt].mx,mx);
            cmax(tree[rt].cov,mx);
            return;
        }
        update(rt);
        int mid = tree[rt].mid();
        if(r<=mid)modify(l,r,mx,lson);
        else if(l>mid)modify(l,r,mx,rson);
        else {
            modify(l,r,mx,lson);
            modify(l,r,mx,rson);
        }
        tree[rt].mx = max( tree[lson].mx,tree[rson].mx );
    }
    
    int ask(int pos,int rt) {
        if(tree[rt].l==tree[rt].r)
            return tree[rt].mx;
        update(rt);
        int mid = tree[rt].mid();
        if(pos<=mid)return ask(pos,lson);
        else return ask(pos,rson);
    }
    
    int ch[MAXN][kind],fail[MAXN];
    int val[MAXN];
    int st[MAXN],ed[MAXN];
    int tot,tim;
    vector<int> adj[MAXN];
    
    inline void set(int x) {
        Clear(ch[x]);
        fail[x] = 0;
        adj[x].clear();
    }
    inline void init() {
        set(1);
        tot = 1;
    }
    inline int newNode() {
        set(++tot);
        return tot;
    }
    inline int ind(char c) {
        return c-'a';
    }
    
    inline void ins(int x,int y,int val) {
        int r = 1;
        REP(i,x,y) {
            int c = ind(s[i]);
            if(ch[r][c]==0)
                ch[r][c] = newNode();
            r = ch[r][c];
        }
    }
    
    inline void build() {
        queue<int> q;
        q.push(1);
        while(!q.empty()) {
            int r = q.front();
            q.pop();
            if(fail[r])
                adj[ fail[r] ].pb(r);
            rep(c,kind) {
                int x = ch[r][c];
                if(!x)continue;
                q.push(x);
    
                int y = fail[r];
                while(y&&ch[y][c]==0)
                    y = fail[y];
                fail[x] = y?ch[y][c]:1;
            }
        }
    }
    
    void dfs(int x) {
        st[x] = ++ tim;
        foreach(i,adj[x]) {
            int y = adj[x][i];
            dfs(y);
        }
        ed[x] = tim;
    }
    
    inline int run() {
        init();
    
        int n;
        RD(n);
        rep1(i,n) {
            scanf("%s",s+beg[i-1]);
            RD(val[i]);
            beg[i] = beg[i-1]+strlen(s+beg[i-1]);
            ins(beg[i-1],beg[i]-1,val[i]);
        }
        build();
    
        tim = 0;
        dfs(1);
        build(1,tim,1);
    
        int ans = 0;
        rep1(i,n) {
            int r = 1;
            int now = 0;
            for(int j=beg[i-1]; j<beg[i]; j++) {
                int c = ind(s[j]);
                r = ch[r][c];
                cmax(now,ask( st[r],1 ));
            }
            now += val[i];
            modify(st[r],ed[r],now,1);
            cmax(ans,now);
        }
        return ans;
    }
    
    int main() {
    
    #ifndef ONLINE_JUDGE
        freopen("sum.in","r",stdin);
        //freopen("sum.out","w",stdout);
    #endif
    
        int ssize = 128 << 20; // 256MB
        char *ppp = (char*)malloc(ssize) + ssize;
        __asm__("movl %0, %%esp
    " :: "r"(ppp) );
    
        int ncase,Ncase = 0;
        RD(ncase);
        while(ncase--)
            printf("Case #%d: %d
    ",++Ncase,run());
    
        return 0;
    }
    

      

  • 相关阅读:
    XML学习笔记(七)Schema语法杂项
    UML和模式应用第一部分:绪论
    XML学习笔记(六)Schema语法之复杂类型
    XML学习笔记(四)Schema介绍篇
    XML学习笔记(三)进阶篇
    Xml学习笔记(二)Javascript篇
    AutoItLibrary安装报错(robotframework)解决
    robot framework 上个用例的输出作为下个用例的输入 (Set Global Variable的用法)
    robot framework ——关键字run keyword if 如何在一个条件下接多个执行语句,以及如何写复杂条件句
    robot framework 如何获取隐藏元素的文本,以及可见元素的文本
  • 原文地址:https://www.cnblogs.com/yejinru/p/3353472.html
Copyright © 2020-2023  润新知