HDU 4117 GRE Words AC自动机+线段树

http://blog.csdn.net/no__stop/article/details/12287843

#include<iostream>
#include<queue>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

using namespace std;

const int MAXN=400005;
int li[MAXN],num[MAXN];
int le[MAXN],ri[MAXN];
int col[MAXN<<2],mx[MAXN<<2],to[MAXN];
int dp[MAXN];

struct Edge
{
    int t;
    int next;
};

Edge edge[MAXN<<1];
int head[MAXN],T,cnt;

void new_edge(int a,int b)
{
    edge[T].t=b;
    edge[T].next=head[a];
    head[a]=T++;
}

/* ----- Segment Tree Start ----- */

inline void push_up(int rt)
{
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}

inline void push_down(int rt)
{
    if (col[rt])
    {
        col[rt<<1]=max(col[rt<<1],col[rt]);
        col[rt<<1|1]=max(col[rt<<1|1],col[rt]);
        mx[rt<<1]=max(mx[rt<<1],col[rt]);
        mx[rt<<1|1]=max(mx[rt<<1|1],col[rt]);
        col[rt]=0;
    }
}

void build(int l,int r,int rt)
{
    col[rt]=mx[rt]=0;
    if (l==r) return;
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    push_up(rt);
}

void update(int a,int b,int c,int l,int r,int rt)
{
    if (a<=l&&r<=b)
    {
        col[rt]=max(c,col[rt]);
        mx[rt]=max(c,mx[rt]);
        return;
    }
    push_down(rt);
    int m=(l+r)>>1;
    if (a<=m)
        update(a,b,c,l,m,rt<<1);
    if (m<b)
        update(a,b,c,m+1,r,rt<<1|1);
    push_up(rt);
}

int query(int a,int l,int r,int rt)
{
    if (l==r)
        return mx[rt];
    push_down(rt);
    int m=(l+r)>>1;
    int ret=0;
    if (a<=m)
        ret=query(a,l,m,rt<<1);
    else
        ret=query(a,m+1,r,rt<<1|1);
    push_up(rt);
    return ret;
}

/* ----- Segment Tree End ----- */

struct AC_Auto
{
    queue<int> q;
    int tot;
    int c[MAXN][26],fail[MAXN],val[MAXN];

    inline int new_node()
    {
        for (int i=0; i<26; i++)
            c[tot][i]=0;
        fail[tot]=val[tot]=0;
        return tot++;
    }

    inline int index(char c)
    {
        return c-'a';
    }

    void insert(char *s,int id)
    {
        int len=strlen(s);
        int now=0;
        for (int i=0; i<len; i++)
        {
            int k=index(s[i]);
            if (!c[now][k]) c[now][k]=new_node();
            now=c[now][k];
        }
        to[id]=now;
    }

    void get_fail()
    {
        int u=0;
        for (int i=0; i<26; i++) if (c[u][i]) q.push(c[u][i]);
        while (!q.empty())
        {
            u=q.front();
            q.pop();
            for (int i=0; i<26; i++)
            {
                if (c[u][i])
                {
                    int e=c[u][i];
                    int j=fail[u];
                    fail[e]=c[j][i];
                    q.push(e);
                }
                else c[u][i]=c[fail[u]][i];
            }
        }
    }

    void init()
    {
        tot=0;
        new_node();
    }

    void dfs(int u,int fa)
    {
        le[u]=++cnt;
        for (int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].t;
            if (v==fa) continue;
            dfs(v,u);
        }
        ri[u]=cnt;
    }

    void connect()
    {
        cnt=0;
        memset(head,-1,sizeof(head));
        for (int i=1; i<tot; i++)
        {
            new_edge(fail[i],i);
            new_edge(i,fail[i]);
        }
        dfs(0,-1);
    }

    void work(char *s,int t)
    {
        int now=0;
        int ans=0,mx=0;
        build(1,cnt,1);
        for (int i=0; i<t; i++)
        {
            int k=index(s[i]);
            now=c[now][k];
            mx=max(mx,query(le[now],1,cnt,1));
            if (li[i])
            {
                int add=num[li[i]]>0?num[li[i]]:0;
                ans=max(ans,mx+add);
                update(le[now],ri[now],mx+add,1,cnt,1);
                now=mx=0;
            }
        }
        printf("%d\n",ans);
    }
};

AC_Auto ac;
char s1[MAXN];
char s2[MAXN];

int main()
{
    int C,n,cases=0;
    scanf("%d",&C);
    while (C--)
    {
        scanf("%d",&n);
        ac.init();
        int t=0;
        T=0;
        memset(li,0,sizeof(li));
        for (int i=1; i<=n; i++)
        {
            scanf("%s%d",s1,&num[i]);
            ac.insert(s1,i);
            int len=strlen(s1);
            for (int j=0; j<len; j++)
                s2[t++]=s1[j];
            li[t-1]=i;
        }
        ac.get_fail();
        ac.connect();
        printf("Case #%d: ",++cases);
        ac.work(s2,t);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值