标签:contain efi tar void bre user com careful turn
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define MAX 1000000 using namespace std; struct Trie { Trie *Next[26],*Fail; int sum; Trie() { for(int i = 0;i < 26;i ++) { Next[i] = NULL; } Fail = NULL; sum = 0; } }*root; void Insert_Str(char *s) {///字符串插入到字典树中 Trie *r = root; int i = -1; while(s[++ i]) { int d = s[i] - ‘a‘; if(r -> Next[d] == NULL) { r -> Next[d] = new Trie(); } r = r -> Next[d]; } r -> sum ++;///结尾加1 } void Build_Fail() {///通过父结点的Fail更新子结点的Fail Trie *node,*temp; queue<Trie *> q; q.push(root); while(!q.empty()) { node = q.front(); q.pop(); for(int i = 0;i < 26;i ++) { if(node -> Next[i]) {///第i个儿子存在 temp = node -> Fail;///temp赋值当前节点的Fail while(temp) { if(temp -> Next[i]) { node -> Next[i] -> Fail = temp -> Next[i]; break; } temp = temp -> Fail; } if(temp == NULL) {///没找到或者本来就是根节点 node -> Next[i] -> Fail = root; } q.push(node -> Next[i]); } } } } int Ac_automation(char *s) { int i = -1,ans = 0; Trie *node = root,*temp; while(s[++ i]) { int d = s[i] - ‘a‘; while(node != root && node -> Next[d] == NULL) node = node -> Fail;///如果没有匹配的子结点 就找它的Fail看看有没有匹配的子结点 if(node -> Next[d]) node = node -> Next[d]; temp = node; while(temp && temp -> sum >= 0) { ans += temp -> sum; temp -> sum = -1;///出现了 再出现时不再计算 temp = temp -> Fail;///找最长后缀 } } return ans; } int main() { int t,n; char tr[50],s[MAX]; scanf("%d",&t); while(t --) { root = new Trie(); scanf("%d",&n); for(int i = 0;i < n;i ++) { scanf("%s",tr); Insert_Str(tr); } Build_Fail(); scanf("%s",s); printf("%d\n",Ac_automation(s)); } }
标签:contain efi tar void bre user com careful turn
原文地址:https://www.cnblogs.com/8023spz/p/9786936.html