HDU 6138 Fleet of the Eternal Throne

来源:互联网 发布:大学英语6级听力知乎 编辑:程序博客网 时间:2024/06/14 17:08

AC自动机。所有的串都插入字典树跑失配。结点val值标为字典树上的深度。
对于每对串,前一个串先跑一遍匹配把点都标记下,后一个串跑一下去标记过的最深点就可以了。

代码:

#include<bits/stdc++.h>using namespace std;const int N = 1e5+5;const int MAXNODE = N<<2, SIGMA_SIZE = 26;#define CLR(A, X) memset(A, X, sizeof(A))struct AC {    int ch[MAXNODE][SIGMA_SIZE], f[MAXNODE], val[MAXNODE], last[MAXNODE], sz;    int vis[MAXNODE];    int idx(char ch) { return ch-'a'; }    void init() { sz = 1; val[0] = 0; CLR(ch[0], 0); CLR(vis, 0); }    int 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]) {                CLR(ch[sz], 0);                val[sz] = val[u]+1;                ch[u][c] = sz++;            }            u = ch[u][c];        }        return u;    }    int Find(char* T, int op, int x) {        int n = strlen(T), ret = 0;        for(int i = 0, j = 0; i < n; i++) {            int c = idx(T[i]);            int t = j = ch[j][c];            while(t) {                if(op == 1) vis[t] = x;                else if(vis[t] == x) ret = max(ret, val[t]);                t = last[t];            }        }        return ret;    }    void getFail() {        queue<int> Q;        f[0] = 0;        for(int c = 0; c < SIGMA_SIZE; c++) {            int u = ch[0][c];            if(u) { f[u] = 0; Q.push(u); last[u] = 0; }        }        while(!Q.empty()) {            int r = Q.front(); Q.pop();            for(int c = 0; c < SIGMA_SIZE; 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];                last[u] = val[f[u]] ? f[u] : last[f[u]];            }        }    }}A;char *str[N], s[N];int main() {    int T, n, m;    scanf("%d", &T);    while(T--) {        scanf("%d", &n);        A.init();        for(int i = 0, j = 0; i < n; i++) {            scanf("%s", s+j);            str[i] = s+j;            A.Insert(s+j);            j = j+strlen(s+j)+1;        }        A.getFail();        scanf("%d", &m);        while(m--) {            int u, v;            scanf("%d%d", &u, &v);            u--, v--;            A.Find(str[u], 1, m+1);            printf("%d\n", A.Find(str[v], 2, m+1));        }    }    return 0;}
原创粉丝点击