AC自动机 模板
2016-06-14 07:50
411 查看
AC自动机模板
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 500; const int inf = 1e9; int minv[maxn] , n ; char base[maxn] , str[maxn]; struct AC_Auto{ const static int LetterSize = 26; const static int TrieSize = 26 * ( 1e5 + 50); int tot; int fail[TrieSize]; int suffixlink[TrieSize]; struct node{ int ptr[LetterSize]; int val; }tree[TrieSize]; inline int GetLetterIdx(char c){ return c - 'a'; } void init_node(node & s){ memset( s.ptr , 0 , sizeof( s.ptr ) ); s.val = 0; } void find(const char * str){ int len = strlen( str ); int j = 0; for(int i = 0 ; i < len ; ++ i){ int idx = GetLetterIdx( str[i] ); while(j && !tree[j].ptr[idx]) j = fail[j]; j = tree[j].ptr[idx]; if(suffixlink[j]) minv[i] = suffixlink[j]; else minv[i] = 0; } } void insert(const char * str){ int len = strlen( str ); int cur = 0; for(int i = 0 ; i < len ; ++ i){ int idx = GetLetterIdx( str[i] ); if(!tree[cur].ptr[idx]){ tree[cur].ptr[idx] = tot; init_node( tree[tot++] ); } cur = tree[cur].ptr[idx]; } if(tree[cur].val == 0) tree[cur].val = len; else tree[cur].val = min( tree[cur].val , len ); } void build_fail(){ queue < int > Q; // 开在栈中 , 如果节点数较多 , 可设为全局变量 suffixlink[0] = fail[0] = 0; for(int i = 0 ; i < LetterSize ; ++ i) if(tree[0].ptr[i]){ int index = tree[0].ptr[i]; fail[index] = 0 , suffixlink[index] = tree[index].val; Q.push( index ); } while(!Q.empty()){ int x = Q.front() ; Q.pop(); for(int i = 0 ; i < LetterSize ; ++ i) if(tree[x].ptr[i]){ int v = tree[x].ptr[i]; int j = fail[x]; while( j && !tree[j].ptr[i] ) j = fail[j]; fail[v] = tree[j].ptr[i]; suffixlink[v] = suffixlink[fail[v]]; if(suffixlink[v] == 0){ if(suffixlink[x]) suffixlink[v] = suffixlink[x] + 1; } else if(suffixlink[x]) suffixlink[v] = min( suffixlink[v] , suffixlink[x] + 1 ); if(tree[v].val){ if(suffixlink[v]==0) suffixlink[v] = tree[v].val; else suffixlink[v] = min( suffixlink[v] , tree[v].val ); } Q.push( v ); } } } void init(){ tot = 1 ; init_node( tree[0] );} }ac_auto; int main(int argc,char *argv[]){ int Case , cas = 1; scanf("%d" , &Case); while(Case--){ scanf("%s%d",base,&n); ac_auto.init(); for(int i = 0 ; i < n ; ++ i){ scanf("%s" , str); ac_auto.insert( str ); } ac_auto.build_fail(); ac_auto.find( base ); int len = strlen( base ); long long ans = 0 ; int last = 0; for(int i = 0 ; i < len ; ++ i){ if(minv[i] == 0) ans += ( i - last + 1 ); else ans += minv[i] - 1 , last = max( last , i + 2 - minv[i] ); } printf("Case #%d: %lld\n" , cas++ , ans ); } return 0; }
相关文章推荐
- 模板函数
- 类的析构及虚析构探究
- Splay 模板
- 模板 SBT
- 模板 快速询问GCD
- 类多继承及虚继承探研
- Android Vibrator的使用
- Educational Codeforces Round 13 A. Johny Likes Numbers 水题
- kafka之一个简单的producer
- 【bzoj1692】【队列变幻】【贪心+后缀数组】
- 二叉树遍历的基本方法(递归与非递归)
- Scrapy的架构初探
- Linux常用20个命令
- 多态性和实现——动物应该这样叫
- 敏捷开发之Scrum扫盲篇
- 在VMware上面安装Solaris 10
- jquery源码学习笔记二:jQuery工厂
- jQuery 3.0 的 Data 浅析
- jquery源码学习笔记二:jQuery工厂
- 浏览器缓存