HDU 6138 AC自动机

来源:互联网 发布:淘宝产品规划方案 编辑:程序博客网 时间:2024/06/14 22:15

题目链接


比赛时队友轻松切掉的水题= =,但我是最近抽时间学了一下AC自动机才理解了此题的正确思路。

个人感觉AC自动机就是一棵升级的Trie树,构造的思想又和KMP雷同,入门还是非常容易的~


思路:
将所有串都丢进AC自动机,每个节点记录一下深度。
每个询问对自动机询问两次,第一次询问进行染色,第二次询问针对染色过的节点更新答案。

代码:

#include<queue>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const int A = 1e5 + 10;const int alp = 26;char s[A];int pos[A];class AC{public:    int Trie[A][alp],val[A],f[A],col[A],sz,root;    int newnode(){        memset(Trie[sz],0,sizeof(Trie[sz]));        f[sz] = val[sz] = col[sz] = 0;        return sz++;    }    void init(){        sz = 0;root = newnode();    }    void insert(char *s){        int len = strlen(s),u = root;        for(int i=0 ;i<len ;i++){            int id = s[i] - 'a';            if(!Trie[u][id]) Trie[u][id] = newnode();            val[Trie[u][id]] = val[u] + 1;            u = Trie[u][id];        }    }    void build(){        queue<int> que;        que.push(root);        while(!que.empty()){            int u = que.front();que.pop();            for(int i=0 ;i<alp ;i++){                int v = Trie[u][i];                if(!v) Trie[u][i] = Trie[f[u]][i];                else   que.push(v);                if(u&&v) f[v] = Trie[f[u]][i];            }        }    }    int query(char* s,int c,bool sta){        int len = strlen(s),u = root,ans = 0;        for(int i=0 ;i<len ;i++){            int id = s[i] - 'a';            u = Trie[u][id];            int tem = u;            while(tem){                if(!sta)                col[tem] = c;                else if(col[tem] == c)  ans = max(ans,val[tem]);                tem = f[tem];            }        }        return ans;    }}ac;int main(){    int T;scanf("%d",&T);    while(T--){        int n;scanf("%d",&n);        int now = 0;ac.init();        for(int i=1 ;i<=n ;i++){            pos[i] = now;            scanf("%s",s+now);            ac.insert(s+now);            int len = strlen(s+now);            now += len+1;        }        ac.build();        int q;scanf("%d",&q);        for(int i=1;i<=q ;i++){            int x,y;            scanf("%d%d",&x,&y);            ac.query(s+pos[x],i,0);            int ans = ac.query(s+pos[y],i,1);            printf("%d\n",ans);        }    }    return 0;}