HDU5880 Family View(AC自动机)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5880 Family View(AC自动机)相关的知识,希望对你有一定的参考价值。
题意:将匹配的串用‘*’代替
tips:
1 注意内存的使用,据说g++中指针占8字节,c++4字节,所以用g++交会MLE
2 注意这种例子,
1
2
abcd
bc
abc
故失败指针要一直往下走,否则会丢弃一些串
3 当出现非英文字符时应先将指针指向根节点,否则出现
1
1
cy
c,,,,,,,y
时结果为c,,,,,,**(由不止一种Bug造成的),正确的应为c,,,,,,,y,然而很多题解这样也过了~
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<utility> using namespace std; typedef long long LL; int Hash[128]; const int N = 1000008, CH = 26; struct Trie{ Trie *next[CH]; Trie *fail; int len; }; int flag[N]; char str[N]; class ACauto{ Trie tree[N]; private: int nxt; Trie *root; public: void init(){ root = &tree[0]; nxt=0; memset(&tree[0], 0, sizeof(Trie)); memset(flag, 0, sizeof(flag)); } void insert(char *s){ Trie *p = root; int i; for(i = 0; s[i]; i++){ int c = Hash[s[i]]; if(!p -> next[c]){ memset(&tree[++nxt], 0, sizeof(Trie)); p -> next[c] = &tree[nxt]; } p = p -> next[c]; } //p -> cnt = 1; //p -> cnt++;//用于统计 p -> len = i; } void build(){ queue<Trie *> q; q.push(root); root -> fail = NULL; while(!q.empty()){ Trie *now = q.front(); q.pop(); for(int i = 0; i < CH; i++){ Trie *son = now -> next[i]; Trie *tp = (now == root)? root: now -> fail->next[i]; if(son == NULL){ now -> next[i] = tp;//Trie图 }else{ son -> fail = tp; //状态合并(如一个串是另一个串的子串则值域可以合并) //son -> cnt += son -> fail -> cnt; q.push(son); } } } } //查询匹配次数 void query(char *s){ Trie *now = root; for(int i = 0; s[i]; i++){ int c = Hash[s[i]]; if(c == -1){ //注意,要将now赋值为root now = root; continue; } now = now -> next[c]; Trie *p = now; while(p != root){ if(p -> len){ flag[i - p -> len + 1]--; flag[i + 1]++; } p = p -> fail; } } } }ac; int main(){ fill(Hash, Hash + 128, -1); for(int i = ‘a‘; i <= ‘z‘; i++){ Hash[i] = i - ‘a‘; } for(int i = ‘A‘; i <= ‘Z‘; i++){ Hash[i] = i - ‘A‘; } int t; cin >>t; while(t--){ ac.init(); int n; scanf("%d", &n); for(int i = 0; i < n; i++){ scanf("%s", str); ac.insert(str); } ac.build(); getchar(); gets(str); ac.query(str); LL cnt = 0; for(int i = 0; str[i]; i++){ cnt += flag[i]; if(cnt >= 0){ putchar(str[i]); }else{ putchar(‘*‘); } } printf("\n"); } return 0; }
以上是关于HDU5880 Family View(AC自动机)的主要内容,如果未能解决你的问题,请参考以下文章