AC自动机模板
来源:互联网 发布:if you中文网络歌手 编辑:程序博客网 时间:2024/06/05 08:17
昨天晚上来基地看了看AC自动机,大概知道是怎么回事了,敲了一遍kuangbin的模板,还是可以理解的,下面就是对其模板的解析。
/*求目标串中出现了多少个模式串*/#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<queue>#include<iostream>using namespace std;const int maxn = 1e4+10;const int maxl = 50+10;const int maxm = 1e6+10;int n;char P[maxl];//模式串char T[maxm];//主串struct Trie{ int nxt[maxn*maxl][26];//Trie树 int fail[maxn*maxl];//前缀指针,在字符串失配时确定转移的结点 int end[maxn*maxl];//表示当前位置的结点是不是某个单词的结束结点 int root, L;//根结点,当前结点 //给Trie树新建一个结点 int newnode() { for( int i = 0; i < 26; i++)//新建结点的子节点都为空 nxt[L][i] = -1; end[L++] = 0;//非结束结点 return L-1;//返回当前结点数 } //Trie树初始化 void init() { L = 0;//树空 root = newnode();//新建一个根节点 } // 向Trie树中插入模式串 void insert( char buf[]) { int len = strlen(buf);//模式串长度 int now = root;//从根节点开始 for( int i = 0; i < len; i++) { if( nxt[now][buf[i]-'a'] == -1)//当前字母的结点不存在 nxt[now][buf[i]-'a'] = newnode();//新建一个 now = nxt[now][buf[i]-'a'];//走到当前字母所在结点 } end[now]++;//标记一下串结束的位置 } // 建失配表 void build() { queue<int> Q;//队列 fail[root] = root;//根节点的fail指向自己 //这里保证根节点的子节点的fail都指向根 for( int i = 0; i < 26; i++)//遍历根节点的26个子节点 { if( nxt[root][i] == -1)//如果子节点不存在 nxt[root][i] = root;//???? else//子节点存在 { fail[nxt[root][i]] = root;//子节点的fail指向根节点 Q.push(nxt[root][i]);//子节点进栈 } } //对于子节点存在的结点 while( !Q.empty()) { //取出栈中的结点 int now = Q.front(); Q.pop(); for( int i = 0; i < 26; i++)//遍历当前结点的子节点 { if( nxt[now][i] == -1)//子节点不存在 nxt[now][i] = nxt[fail[now]][i];//???? else { fail[nxt[now][i]] = nxt[fail[now]][i];//当前结点的fail沿着父亲的fail走,指向父亲fail的与自己值相同的子节点 Q.push(nxt[now][i]);//当前结点进栈 } } } } int query( char buf[]) { int len = strlen(buf);//主串的长度 int now = root;//指向根节点 int res = 0; for( int i = 0; i < len; i++)//遍历主串 { now = nxt[now][buf[i]-'a'];//当前字符在Trie树中的位置 int tmp = now; while( tmp != root)//==的话为空,前面记录了的,!=代表存在 { res += end[tmp];//看是否为一个完整的串,是的话就加到res里 end[tmp] = 0;//标记已经计算过 tmp = fail[tmp];//指向fail指针 } } return res; }};char buf[1000000];Trie ac;int main(){ int T_T; scanf("%d",&T_T); while( T_T--) { scanf("%d",&n); ac.init(); for( int i = 0; i < n; i++) { scanf("%s",P); ac.insert(P); } ac.build(); scanf("%s",T); printf("%d\n",ac.query(T)); } return 0;}
阅读全文
0 0
- 【AC自动机】AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板
- AC自动机模板 hdu2222
- AC自动机模板
- AC自动机模板
- 数据结构--AC自动机--模板
- ac自动机模板
- AC自动机模板
- AC自动机模板
- hdu2222 ac自动机模板
- ac自动机模板。。。。。
- AC自动机模板 LA4670
- AC自动机模板
- ssm 拦截器
- Timer与ScheduledExecutorService
- springboot+mybatis分页插件pageHelper的配置与使用
- java内存泄漏
- MyBatis动态sql_where查询条件
- AC自动机模板
- Linux下安装Samba共享文件
- 应用程序打包神器Inno setup
- LeetCode——Palindrome Linked List
- mysql创建高性能的索引
- [BZOJ3669][Noi2014]魔法森林(动态spfa)
- 1231231
- 模拟实现 ListIterator类
- Android中的ListView响应item内部按钮点击事件