题目大意:输入几个子串,然后输入一个母串,问在母串里面包含几个子串。
分析:刚学习的AC自动机,据说这是个最基础的模板题,所以也是用了最基本的写法来完成的,当然也借鉴了别人的代码思想,确实是个很神奇的东西,如果不懂KMP的话,最好先学学KMP再来学这个,会理解的更深刻一些。
代码如下:
=======================================================================================================================
#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> using namespace std; const int MAXN = 1e6+7; const int MAXM = 26; const int oo = 1e9+37; char MumStr[MAXN];///母串 struct Ac_Trie_Node {///Fail 失败节点 Ac_Trie_Node *Fail, *next[MAXM]; int leaf;///已这个节点为叶子节点的数目 }; void Insert(Ac_Trie_Node *root, char s[]) {///插入所有的模式串 Ac_Trie_Node *p = root; for(int i=0; s[i]; i++) { int k = s[i]-'a'; if(p->next[k] == NULL) p->next[k] = new Ac_Trie_Node(); p = p->next[k]; } p->leaf += 1; } void GetFail(Ac_Trie_Node *root) {///构造失败指针 queue<Ac_Trie_Node *> Q; Ac_Trie_Node *p = root, *temp; for(int i=0; i<MAXM; i++) { if(p->next[i] != NULL) { p->next[i]->Fail = root; Q.push(p->next[i]); } } while(Q.size()) { p = Q.front();Q.pop(); for(int i=0; i<MAXM; i++) if(p->next[i]) {///如果节点p的next[i]不为空 temp = p->Fail;///查找另一个最近的next[i]不为空的地方 while(temp != NULL) { if(temp->next[i] != NULL) {///查找到 p->next[i]->Fail = temp->next[i]; break; } temp = temp->Fail; } if(temp == NULL) p->next[i]->Fail = root; Q.push(p->next[i]); } } } void FreeTrie(Ac_Trie_Node *root) {///释放内存 Ac_Trie_Node *p = root; for(int i=0; i<MAXM; i++) { if(p->next[i] != NULL) FreeTrie(p->next[i]); } free(p); } int Query(Ac_Trie_Node *root) { Ac_Trie_Node *p = root, *temp; int sum=0; for(int i=0; MumStr[i]; i++) { int k = MumStr[i]-'a'; while(!p->next[k] && p != root) p = p->Fail; if(!p->next[k])continue;///根节点下面没有这个字母 temp = p = p->next[k]; while(temp != root && temp->leaf != -1) {///查找路径上的所有子节串,因为每个子串只出现一次,所以赋值为-1,防止重搜 sum += temp->leaf; temp->leaf = -1; temp = temp->Fail; } } return sum; } int main() { int T; scanf("%d", &T); while(T--) { int M; char s[107]; Ac_Trie_Node *root = new Ac_Trie_Node(); scanf("%d", &M); while(M--) { scanf("%s", s); Insert(root, s); } GetFail(root); scanf("%s", MumStr); int ans = Query(root); printf("%d ", ans); FreeTrie(root); } return 0; }