- //======================
- // HDU 2222
- // 求目标串中出现了几个模式串
- //====================
- #include <stdio.h>
- #include <algorithm>
- #include <iostream>
- #include <string.h>
- #include <queue>
- using namespace std;
- struct Trie
- {
- int Next[500010][26];//26是这里讨论26个小写字母的情况,根据情况修改
- int fail[500010],end[500010];//end数组表示以该节点结尾的字符串的数量
- int root,L;//L用来标记节点序号,以广度优先展开的字典树的序号
- int newnode() //建立新节点
- {
- for(int i = 0;i < 26;i++)
- Next[L][i] = -1; //将该节点的后继节点域初始化
- end[L++] = 0;
- return L-1; //返回当前节点编号
- }
- void init() //初始化操作
- {
- L = 0;
- root = newnode();
- }
- void insert(char buf[])
- {
- int len = strlen(buf);
- int now = root;
- for(int i = 0;i < len;i++)
- {
- if(Next[now][buf[i]-‘a‘] == -1) //如果未建立当前的后继节点,建立新的节点
- Next[now][buf[i]-‘a‘] = newnode();
- now = Next[now][buf[i]-‘a‘];
- }
- end[now]++;//以该节点结尾的字符串数量增加1
- }
- void build()
- {
- queue<int>Q; //用广度优先的方式,将树层层展开
- fail[root] = root;
- for(int i = 0;i < 26;i++)
- if(Next[root][i] == -1)
- Next[root][i] = root;
- else
- {
- fail[Next[root][i]] = root;
- Q.push(Next[root][i]);
- }
- while( !Q.empty() )
- {
- int now = Q.front();
- Q.pop();
- for(int i = 0;i < 26;i++)
- if(Next[now][i] == -1)
- Next[now][i] = Next[fail[now]][i];//该段的最后一个节点匹配后,跳到拥有最大公共后缀的fail节点继续匹配
- else
- {
- fail[Next[now][i]]=Next[fail[now]][i];//当前节点的fail节点等于它前驱节点的fail节点的后继节点
- Q.push(Next[now][i]);
- }
- }
- }
- int query(char buf[])
- {
- int len = strlen(buf);
- int now = root;
- int res = 0;
- for(int i = 0;i < len;i++)
- {
- now = Next[now][buf[i]-‘a‘];
- int temp = now;
- while( temp != root )
- {
- res += end[temp];//加上以当前节点结尾的字符串数
- end[temp] = 0;//该题是防止计算重复的字符串
- temp = fail[temp];//每次找最大公共后缀对应的fail节点
- }
- }
- return res;
- }
- void debug()
- {
- for(int i = 0;i < L;i++)
- {
- printf("id = =,fail = =,end = =,chi = [",i,fail[i],end[i]);
- for(int j = 0;j < 26;j++)
- printf("-",Next[i][j]);
- printf("]\n");
- }
- }
- };
- char buf[1000010];
- Trie ac;
- int main()
- {
- int t,n,ans;
- scanf("%d",&t);
- while(t--)
- {
- ac.init();
- scanf("%d",&n);
- for(int i=0;i<n;i++)
- {
- scanf("%s",buf);
- ac.insert(buf);
- }
- ac.build();
- scanf("%s",buf);
- printf("%d\n",ac.query(buf));
- }
- return 0;
- }
来源: http://www.bubuko.com/infodetail-2311974.html