HDU 2846 ac自动机 给定n个串 q个询问 问是n个串中几个串的子串

来源:互联网 发布:it监控软件 编辑:程序博客网 时间:2024/06/05 02:54

注意每个串只能成为一个串的子串 only once

所以用set去重


#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <set>#include <math.h>#include <queue>using namespace std;#define ll __int64#define N 10010  #define inf 100000000000000#define maxnode 250001#define sigma_size 26struct Trie{int ch[maxnode][sigma_size];int val[maxnode]; //该单词在模式串中出现的次数int last[maxnode];int f[maxnode]; //失配数组int num[maxnode]; //该单词出现在文本串的次数int pre[maxnode];    //该单词的前驱int len[maxnode];    //以该单词结尾的单词长度int Char[maxnode]; //该单词对应的字母int sz;void init(){sz=1;memset(ch,0,sizeof(ch));memset(val, 0, sizeof(val));  memset(f,0,sizeof(f));memset(last,0,sizeof(last));    //记录该节点前一个节点是谁memset(len, 0, sizeof(len));}int idx(char c){ return c-'a'; }int insert(char *s){int u = 0;for(int i = 0; s[i] ;i++){int c = idx(s[i]);if(!ch[u][c])ch[u][c] = sz++;pre[ch[u][c]] = u;Char[ch[u][c]] = s[i];len[ch[u][c]] = len[u]+1;u = ch[u][c];}val[u] = 1;num[u] = 0;return u;}   void getFail(){            queue<int> q;            for(int i = 0; i<sigma_size; i++)                if(ch[0][i]) q.push(ch[0][i]);                while(!q.empty()){                int r = q.front(); q.pop();                for(int c = 0; c<sigma_size; c++){                    int u = ch[r][c];                    if(!u)continue;                    q.push(u);                    int v = f[r];                    while(v && ch[v][c] == 0) v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环                    f[u] = ch[v][c];                }            }        }    void find(char *T){set<int>myset; myset.clear();int j = 0;for(int i = 0; T[i] ; i++){int c = idx(T[i]);while(j && ch[j][c]==0) j = f[j];j = ch[j][c];int temp = j;while(temp){ //沿失配边走 || 若沿失配边走时一定要节点为单词结尾则改成while(temp && val[temp])if(myset.find(temp)==myset.end()){myset.insert(temp);num[temp]++;}temp = f[temp];}}}}ac;int Stack[100010];char s[30], hehe[N][30];int main(){int n, que, i;ac.init();scanf("%d",&n);for(i = 0; i < n; i++)scanf("%s",hehe[i]);scanf("%d",&que);for(i = 0; i < que; i++){scanf("%s",s);Stack[i] = ac.insert(s);}ac.getFail();for(i = 0; i < n; i++)ac.find(hehe[i]);for(i = 0; i < que; i++)printf("%d\n",ac.num[Stack[i]]);return 0;}


0 0