【回文自动机】 HDU 5394 Trie in Tina Town

通道

题意:按要求建一棵树,求树上的价值=sum(len*cnt),len为回文长度,cnt为该回文在树上出现了多少次

思路:建好树从0开始往下跑就可以了,每跑完一条链,就回溯下。

代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;

struct Node {
    int p, cur, c, nxt, last;
    Node () {
        
    }
    Node (int _p, int _cu, int _c, int _n, int _l) {
        p = _p; cur = _cu; c = _c; nxt = _n, last = _l;
    }
};

const int MAX_N = 2000007;
const int SIG = 4;
struct PTree {
    int nxt[MAX_N][SIG], fail[MAX_N], len[MAX_N], S[MAX_N];
    int last, n, p;
    ll lenCnt[MAX_N];
    int newNode (int l) {
        memset(nxt[p], 0, sizeof nxt[p]);
        len[p] = l;
        lenCnt[p] = 0;
        return p++;
    }
    void init() {
        p = last = n = 0;
        newNode(0), newNode(-1);
        S[n] = -1;
        fail[0] = 1;
    }
    int getFail(int x) {
        while (S[n - len[x] - 1] != S[n]) x = fail[x];
        return x;
    }
    Node add(int c, ll &ans) {
        c -= 'a';
        S[++n] = c;
        int cur = getFail(last);
        Node now = Node(p, cur, c, nxt[cur][c], last);
        if (!nxt[cur][c]) {
            int now = newNode(len[cur] + 2);
            fail[now] = nxt[getFail(fail[cur])][c];
            nxt[cur][c] = now;
            lenCnt[now] = lenCnt[fail[now]] + len[now];
        }
        last = nxt[cur][c];
        ans += lenCnt[last];
        return now;
    }    
    void pop(Node pre) {
        --n;
        p = pre.p, last = pre.last, nxt[pre.cur][pre.c] = pre.nxt;
    }
};

struct Edge {
    int v, ch, nxt;
    Edge () {
    }
    Edge(int _v, int _ch, int _n) {
        v = _v;
        ch = _ch;
        nxt = _n;
    }
};

Edge E[MAX_N];
int head[MAX_N], ecnt;
PTree A;
ll ans;

void Clear(int n) {
    ecnt = 0; memset(head, -1, sizeof head);
}
void add(int u, int v, int w) {
    E[ecnt] = Edge(v, w, head[u]);
    head[u] = ecnt++;
}
void dfs(int u) { 
    for (int i = head[u]; ~i; i = E[i].nxt) {
        int v = E[i].v, ch = E[i].ch; 
        Node pre = A.add(ch, ans); 
        dfs(v);
        A.pop(pre); 
    }
}

int n;
int main() {
    int T; scanf("%d", &T);
    while (T-- > 0) {
        scanf("%d", &n); int x;
        Clear(n); char s[2]; 
        for (int i = 1; i <= n; ++i) {
            scanf("%s%d", s, &x);
            add(x, i, s[0]);
        }
        ans = 0;
        A.init();
        dfs(0);
        printf("%I64d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2015-08-15 22:40  mithrilhan  阅读(330)  评论(0编辑  收藏  举报