HDU 2846 ac自动机 给定n个串 q个询问 问是n个串中几个串的子串
来源:互联网 发布:it监控软件 编辑:程序博客网 时间:2024/06/05 02:54
注意每个串只能成为一个串的子串 only once
所以用set去重
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <set>#include <math.h>#include <queue>using namespace std;#define ll __int64#define N 10010 #define inf 100000000000000#define maxnode 250001#define sigma_size 26struct Trie{int ch[maxnode][sigma_size];int val[maxnode]; //该单词在模式串中出现的次数int last[maxnode];int f[maxnode]; //失配数组int num[maxnode]; //该单词出现在文本串的次数int pre[maxnode]; //该单词的前驱int len[maxnode]; //以该单词结尾的单词长度int Char[maxnode]; //该单词对应的字母int sz;void init(){sz=1;memset(ch,0,sizeof(ch));memset(val, 0, sizeof(val)); memset(f,0,sizeof(f));memset(last,0,sizeof(last)); //记录该节点前一个节点是谁memset(len, 0, sizeof(len));}int idx(char c){ return c-'a'; }int insert(char *s){int u = 0;for(int i = 0; s[i] ;i++){int c = idx(s[i]);if(!ch[u][c])ch[u][c] = sz++;pre[ch[u][c]] = u;Char[ch[u][c]] = s[i];len[ch[u][c]] = len[u]+1;u = ch[u][c];}val[u] = 1;num[u] = 0;return u;} void getFail(){ queue<int> q; for(int i = 0; i<sigma_size; i++) if(ch[0][i]) q.push(ch[0][i]); while(!q.empty()){ int r = q.front(); q.pop(); for(int c = 0; c<sigma_size; c++){ int u = ch[r][c]; if(!u)continue; q.push(u); int v = f[r]; while(v && ch[v][c] == 0) v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环 f[u] = ch[v][c]; } } } void find(char *T){set<int>myset; myset.clear();int j = 0;for(int i = 0; T[i] ; i++){int c = idx(T[i]);while(j && ch[j][c]==0) j = f[j];j = ch[j][c];int temp = j;while(temp){ //沿失配边走 || 若沿失配边走时一定要节点为单词结尾则改成while(temp && val[temp])if(myset.find(temp)==myset.end()){myset.insert(temp);num[temp]++;}temp = f[temp];}}}}ac;int Stack[100010];char s[30], hehe[N][30];int main(){int n, que, i;ac.init();scanf("%d",&n);for(i = 0; i < n; i++)scanf("%s",hehe[i]);scanf("%d",&que);for(i = 0; i < que; i++){scanf("%s",s);Stack[i] = ac.insert(s);}ac.getFail();for(i = 0; i < n; i++)ac.find(hehe[i]);for(i = 0; i < que; i++)printf("%d\n",ac.num[Stack[i]]);return 0;}
0 0
- HDU 2846 ac自动机 给定n个串 q个询问 问是n个串中几个串的子串
- hdu 1671 Phone List(给定n个电话号码串,问这n个电话号码串中是否存在某一串是其它串的前缀,如果存在输出NO,否则YES)
- 长度为n的密码利用给定的m个串最多有几种组合 AC自动机+DP UVA 1076 - Password Suspects
- SPOJ1812(后缀自动机求n个串的最长公共子串)
- POJ 3415 Life Forms 给定n个字符串,求出现在不小于k个字符串中的最长子串。
- hdu 4416 后缀自动机 问在S中有多少个不同子串满足它不是s1~sn中任意一个字符串的子串
- 三个或N个串的最长公共子序列
- 求n个字符串的最大相同子串
- HDU 4436 str2int(后缀数组,一种统计n个digit字符串所有不同子串之和的方法)
- sdut 1008 最大公共子串(求n个字符串的最长公共子串)
- hdu 2896 ac自动机 目标串中有几个模式串
- 两个或N个字符串最大公共子串算法
- 两个或N个字符串最大公共子串算法
- 两个或N个字符串最大公共子串算法
- 两个或N个字符串最大公共子串算法
- 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。 输入格式 第一行包含一个数n,表示序列长度。 第二行包含n个正整数,表示给定的序列。 第三个包含一个正整数m,表
- 后缀数组(三)求给定字符串不相同的子串个数(hdu 4622 区间询问)
- SGU 411Petya the Hero(最长公共回文子串,AC自动机+n^2判断回文)(学习后缀数组的前奏)
- 开发中的“软”与“硬”:高画质移动游戏开发之道
- Lesson_for_java_day14--java中的泛型、Comparator、Comparable
- COJ 1059 - Numeric Parity 位操作
- [leetcode] Binary Tree Postorder Traversal
- DOS 清屏指令
- HDU 2846 ac自动机 给定n个串 q个询问 问是n个串中几个串的子串
- Web 前端性能优化——控制DOM大小
- 《算法导论》笔记 第13章 13.4 删除
- hadoop的WordCount例子
- OpenCV编程->Image Watch使用
- python学习笔记-命令行参数
- Android之DatePicker和DatePickeDialog基本用法
- C#NotifyIcon类把程序最小化到右下角托盘
- Lesson_for_java_day15--java小练习:贪吃蛇游戏(在控制台上操作)