hdu 4117 GRE Words (ac自动机 线段树 dp)

来源:互联网 发布:gis平台软件 编辑:程序博客网 时间:2024/04/29 05:31

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

此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后缀

然后更新其影响的字符串的方法,即区间更新,维护最大值,用线段树优化。

而其可以影响的字符串为其在fail树中的子树节点


此题一直MLE,调了一下午+晚上。最后发现。

(1)ac自动机中的节点开始直接初始化,应动态初始化(也终于理解了许多人那么做)

(2)还有用vector表示树边时,一开始初始clear,也会耗很多内存。

(3)线段树开始直接初始化CLR(smax, 0)CLR(cov, 0),由于数组比较大,内存耗较大

最后,ac自动机节点动态初始化,用链表模拟表示树边,线段树动态build,终于有MLE变成了wa

怒重敲,终于ac了


PS:一开始使用后缀数组ac的,数据水了。。。

不过ac自动机2s+,后缀数组8s+

ac自动机:

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <ctime>#include <cstdlib>#include <cstring>#include <queue>#include <string>#include <set>#include <stack>#include <map>#include <cmath>#include <vector>#include <iostream>#include <algorithm>using namespace std;#define FE(i, a, b) for(int i = (a); i <= (b); ++i)#define FD(i, b, a) for(int i = (b); i >= (a); --i)#define REP(i, N) for(int i = 0; i < (N); ++i)#define CLR(a, v) memset(a, v, sizeof(a))#define PB push_back#define MP make_pairtypedef long long LL;const int INF = 0x3f3f3f3f;#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1const int MAX = 333333;const int SIG = 26;struct Edge{    int to, next;}adj[MAX * 2];int adj_cnt;int head[MAX];void adj_init(){    adj_cnt = 0;    CLR(head, -1);}void add_edge(int x, int y){    adj[adj_cnt].to = y;    adj[adj_cnt].next = head[x];    head[x] = adj_cnt++;}int tl[MAX], tr[MAX];int tot;char ca[MAX], s[MAX];int id[MAX];int val[MAX];int smax[MAX << 2], cov[MAX << 2];void update_cov(int rt, int x){    smax[rt] = max(smax[rt], x);    cov[rt] = max(cov[rt], x);}void up(int rt){    smax[rt] = max(smax[rt << 1], smax[rt << 1 | 1]);}void down(int rt){    if (cov[rt])    {        update_cov(rt << 1, cov[rt]); update_cov(rt << 1 | 1, cov[rt]);        cov[rt] = 0;    }}void build(int l, int r, int rt)///!!!{    smax[rt] = cov[rt] = 0;    if (l == r) return ;    int m = (l + r) >> 1;    build(lson); build(rson);    up(rt);}void update(int L, int R, int x, int l, int r, int rt){    if (L <= l && r <= R)    {        update_cov(rt, x);        return ;    }    down(rt);    int m = (l + r) >> 1;    if (L <= m) update(L, R, x, lson);    if (R > m) update(L, R, x, rson);    up(rt);}int query(int p, int l, int r, int rt){    if (l == r) return smax[rt];    down(rt);    int m = (l + r) >> 1;    if (p <= m) return query(p, lson);    else return query(p, rson);}struct AC{    int ch[MAX][SIG];    int f[MAX];    int sz;    int newnode()///!!!    {        CLR(ch[sz], 0);        return sz++;    }    void init()    {        sz = 0;        newnode();    }    int idx(char c) { return c-'a'; }    void insert(char *s)    {        int u=0,n=strlen(s);        for(int i=0;i<n;i++)        {            int c=idx(s[i]);            if(!ch[u][c]) ch[u][c] = newnode();            u = ch[u][c];        }    }    void getFail()    {        queue<int> q;        f[0] = 0;        for(int c = 0; c < SIG; c++)        {            int u = ch[0][c];            if(u) { f[u] = 0; q.push(u); }        }        while(!q.empty())        {            int r = q.front(); q.pop();            for(int c = 0; c < SIG; c++)            {                int  u = ch[r][c];                if(!u) { ch[r][c] = ch[f[r]][c]; continue; }                q.push(u);                int v = f[r];                while(v && !ch[v][c]) v = f[v];                f[u] = ch[v][c];            }        }    }    void dfs(int u, int fa)    {        tl[u] = ++tot;        for (int r = head[u]; r != -1; r = adj[r].next)        {            int v = adj[r].to;            if (v != fa) dfs(v, u);        }        tr[u] = tot;    }    void makeTree()    {        adj_init();        for (int i = 1; i < sz; i++)///        {            add_edge(i, f[i]); add_edge(f[i], i);        }        tot = 0;        dfs(0, -1);    }    int solve(char *s)    {        int len = strlen(s);        int u = 0;        int now, ans;        ans = now = 0;        build(1, tot, 1);        for (int i = 0; i < len; i++)        {            u = ch[u][s[i] - 'a'];            int valu = query(tl[u], 1, tot, 1);            now = max(now, valu);            if (id[i])            {                if (val[id[i]] > 0) now += val[id[i]];                ans = max(ans, now);                update(tl[u], tr[u], now, 1, tot, 1);                u = now = 0;            }        }        return ans;    }}ac;int main(){    int len;    int n, m;    int T, nc;    nc = 1;    scanf("%d", &T);    while (T--)    {        scanf("%d", &n);        len = 0;        ac.init();        CLR(id, 0);        for (int i = 1; i <= n;i++)        {            scanf("%s%d", ca, &val[i]);            ac.insert(ca);            int l = strlen(ca);            REP(j, l)            {                s[len++] = ca[j];            }            id[len - 1] = i;        }        ac.getFail();        ac.makeTree();        printf("Case #%d: %d\n", nc++, ac.solve(s));    }}

后缀数组:

//#pragma warning (disable: 4786)//#pragma comment (linker, "/STACK:16777216")//HEAD#include <cstdio>#include <ctime>#include <cstdlib>#include <cstring>#include <queue>#include <string>#include <set>#include <stack>#include <map>#include <cmath>#include <vector>#include <iostream>#include <algorithm>using namespace std;//LOOP#define FF(i, a, b) for(int i = (a); i < (b); ++i)#define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)#define FE(i, a, b) for(int i = (a); i <= (b); ++i)#define FED(i, b, a) for(int i = (b); i>= (a); --i)#define REP(i, N) for(int i = 0; i < (N); ++i)#define CLR(A,value) memset(A,value,sizeof(A))#define CPY(a, b) memcpy(a, b, sizeof(a))#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)//STL#define SZ(V) (int)V.size()#define PB push_back//INPUT#define RI(n) scanf("%d", &n)#define RII(n, m) scanf("%d%d", &n, &m)#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)#define RS(s) scanf("%s", s)//OUTPUT#define WI(n) printf("%d\n", n)#define WS(s) printf("%s\n", s)typedef long long LL;typedef unsigned long long ULL;typedef vector <int> VI;const int INF = 1000000000;const double eps = 1e-10;const int MAXN=110000 * 4;int wa[MAXN], wb[MAXN], wv[MAXN], wn[MAXN];char r[MAXN];int a[MAXN], sa[MAXN], rank[MAXN], height[MAXN];int idx[MAXN];int val[20010];int len[20010];int sumlen[20010];int dp[20010];int cmp(int *r, int a, int b, int k){    return r[a] == r[b] && r[a + k] == r[b + k];}void build_sa(int *r, int *sa, int n, int m){    int i, j, p;    int *x = wa, *y = wb, *t;    for (i = 0; i < m; i++) wn[i] = 0;    for (i = 0; i < n; i++)wn[x[i] = r[i]]++;///    for (i = 1; i < m; i++) wn[i] += wn[i - 1];    for (i = n - 1; i >= 0; i--) sa[--wn[x[i]]] = i;    for (p = 1, j = 1; p < n; j <<= 1, m = p)    {        for (p = 0, i = n - j; i < n; i++) y[p++] = i;        for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;        for (i = 0; i < m; i++) wn[i] = 0;        for (i = 0; i < n; i++) wn[wv[i] = x[y[i]]]++;///        for (i = 1; i < m; i++) wn[i] += wn[i - 1];        for (i = n - 1; i >= 0; i--) sa[--wn[wv[i]]] = y[i];        t = x; x = y; y = t;        x[sa[0]] = 0; p = 1;        for (i = 1; i < n; i++)            x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;    }}void getHeight(int *r, int *sa, int n){    int i, j, k = 0;    for (i = 1; i <= n; i++)    {        rank[sa[i]] = i;        height[i] = 0;    }    for (i = 0; i < n; i++)    {        if (k) k--;        j = sa[rank[i] - 1];        while (r[i + k] == r[j + k]) k++;        height[rank[i]] = k;    }}int getid(int x){    return idx[sa[x]];}int solve(int t, int n){    int sum = 0;    FE(i, 1, t)    {        dp[i] = val[i];        sumlen[i] = sum;        sum += len[i] + 1;    }    int nowi;    FED(i, t, 1)    {        nowi = sumlen[i];        int lmin = INF;        for (int j = rank[nowi] + 1; j <= n; j++)        {            lmin = min(lmin, height[j]);            if (lmin < len[i]) break;            if (nowi < sa[j])                dp[i] = max(dp[i], val[i] + dp[getid(j)]);        }        lmin = INF;        for (int j = rank[nowi] - 1; j > 0; j--)        {            lmin = min(lmin, height[j + 1]);            if (lmin < len[i]) break;            if (nowi < sa[j])                dp[i] = max(dp[i], val[i] + dp[getid(j)]);        }    }    int ans = 0;    FE(i, 1, t) ans = max(ans, dp[i]);    return ans;}int main(){    int test;    int t, n, m;    int ncase = 1;    RI(test);    while (test--)    {        n = 0;        m = 256;        CLR(idx, 0);        RI(t);        FE(i, 1, t)        {            RS(r);            RI(val[i]);            int l = len[i] = strlen(r);            REP(j, l)            {                a[n] = (int)r[j];                idx[n++] = i;            }            a[n++] = m++;        }        a[--n] = 0; --m;        build_sa(a, sa, n + 1, m);        getHeight(a, sa, n);        printf("Case #%d: %d\n", ncase++, solve(t, n));    }    return 0;}



原创粉丝点击