2017多校第6场 HDU 6096 String AC自动机
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6096
题意:给了一些模式串,然后再给出一些文本串的不想交的前后缀,问文本串在模式串的出现次数。
解法:
因为要求前缀后缀都包含的个数,所以可以把字符串a转换成a#a这样一个字符串,比如abca就转换成abca#abca
然后对于一组前缀a后缀b转换成b{a,比如ab ca,就是ca{ab,
然后对前缀后缀的串建立AC自动机,让主串去匹配,如上述例子,ca{ab满足为abca{abca的一个子串,也就是abca满足这个前缀后缀,所以问题,就转换成了典型的ac自动机匹配问题。
加个{的原因是为了只让后缀{前缀这种串能在AC自动机匹配到。
然后求答案的时候,需要对连接到自己的fail的位置累加一下,含义想一下就明白了。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010;
const int maxs = 30;
string s[maxn];
int d[maxn],pos[maxn],ans[maxn],st[maxn],len[maxn];
struct Acautomata{
int nxt[maxn][maxs],cnt[maxn],fail[maxn],match[maxn],dep[maxn];
int L, root;
int newnode(){
for(int i=0; i<maxs; i++) nxt[L][i]=-1;
cnt[L++]=0;
fail[L-1]=0;
return L-1;
}
void init(){
L = 0;
root = newnode();
}
int Insert(string a){
int now=root;
for(int i=0; a[i]; i++){
if(nxt[now][a[i]-'a']==-1){
nxt[now][a[i]-'a']=newnode();
dep[L-1]=i+1;
}
now=nxt[now][a[i]-'a'];
}
cnt[now]=1;
return now;
}
void build()
{
queue<int>q;
int now=root;
fail[0] = 0;
for(int i=0; i<maxs; i++){
if(nxt[now][i]==-1){
nxt[now][i]=root;
continue;
}
else{
fail[nxt[now][i]]=root;
q.push(nxt[now][i]);
}
}
while(!q.empty())
{
now = q.front();
q.pop();
for(int i=0; i<maxs; i++){
if(nxt[now][i]!=-1){
q.push(nxt[now][i]);
fail[nxt[now][i]] = nxt[fail[now]][i];
match[nxt[now][i]] = cnt[nxt[now][i]]?nxt[now][i]:match[nxt[fail[now]][i]];
}else{
nxt[now][i] = nxt[fail[now]][i];
}
}
}
}
void solve1(string a, int h){
int now=root;
int sz = a.size();
for(int i=0; i<sz; i++){
now=nxt[now][a[i]-'a'];
while(dep[now]>h){
now=fail[now];
}
ans[match[now]]++;
}
}
void solve2(){//累加答案,对连到自己的fail进行累加求和
memset(d, 0, sizeof(d));
int j, k = 0;
for(int i=0; i<L; i++) d[fail[i]]++;
for(int i=0; i<L; i++) if(!d[i]) st[k++]=i;
for(int i=0; i<k; i++){
j=fail[st[i]];
ans[j]+=ans[st[i]];
if(!(--d[j])){
st[k++]=j;
}
}
}
}ZXY;
int n, q;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
ZXY.init();
scanf("%d%d", &n,&q);
for(int i=0; i<n; i++){
cin>>s[i];
len[i] = s[i].size()+1;
string temp=s[i];
s[i]+=char('z'+1);
s[i]+=temp;
}
for(int i=0; i<q; i++){
string s1,s2;
cin>>s1>>s2;
s2 = s2 + char('z'+1);
s2 = s2 + s1;
pos[i] = ZXY.Insert(s2);
}
ZXY.build();
for(int i=0; i<n; i++){
ZXY.solve1(s[i],len[i]);
}
ZXY.solve2();
for(int i=0; i<q; i++) printf("%d\n", ans[pos[i]]);
for(int i=0; i<=ZXY.L; i++){
ans[i]=0;
ZXY.match[i]=0;
}
}
return 0;
}
2017多校第6场 HDU 6096 String AC自动机的更多相关文章
- HDU 6096 String (AC自动机)
题意:给出n个字符串和q个询问,每次询问给出两个串 p 和 s .要求统计所有字符串中前缀为 p 且后缀为 s (不可重叠)的字符串的数量. 析:真是觉得没有思路啊,看了官方题解,真是好复杂. 假设原 ...
- 2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6138 题意:给n个串,每次询问x号串和y号串的最长公共子串的长度,这个子串必须是n个串中某个串的前缀 ...
- 2017多校第9场 HDU 6170 Two strings DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6170 题意:给了2个字符串,其中第2个字符串包含.和*两种特别字符,问第二个字符串能否和第一个匹配. ...
- 2017多校第9场 HDU 6161 Big binary tree 思维,类似字典树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6161 题意: 题目是给一棵完全二叉树,从上到下从左到右给每个节点标号,每个点有权值,初始权值为其标号, ...
- 2017多校第9场 HDU 6169 Senior PanⅡ 数论,DP,爆搜
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6169 题意:给了区间L,R,求[L,R]区间所有满足其最小质数因子为k的数的和. 解法: 我看了这篇b ...
- 2017多校第10场 HDU 6181 Two Paths 次短路
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181 题意:给一个图,求出次短路. 解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证 ...
- 2017多校第10场 HDU 6180 Schedule 贪心,multiset
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6180 题意:给了一些任务的开始时间和终止时间,现在让我们安排k台及机器,让这些任务在k太机器上最小,并 ...
- 2017多校第10场 HDU 6178 Monkeys 贪心,或者DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6178 题意:给出一棵有n个节点的树,现在需要你把k只猴子放在节点上,每个节点最多放一只猴子,且要求每只 ...
- 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...
随机推荐
- 【bzoj1742】[Usaco2005 nov]Grazing on the Run 边跑边吃草 区间dp
题目描述 John养了一只叫Joseph的奶牛.一次她去放牛,来到一个非常长的一片地,上面有N块地方长了茂盛的草.我们可以认为草地是一个数轴上的一些点.Joseph看到这些草非常兴奋,它想把它们全部吃 ...
- bzoj 1862: [Zjoi2006]GameZ游戏排名系统 & bzoj 1056: [HAOI2008]排名系统
傻叉了一晚上,把t打成x,然后这题神奇在于输出一段数,不足的不用输出,一开始我的是直接找没有后面就退,然后这样会格式错误囧……然后最后zj的还卡了下空间,于是不用string就过了……string毁一 ...
- JUC包中的分而治之策略-为提高性能而生
一.前言 本次分享我们来共同探讨JUC包中一些有意思的类,包含AtomicLong & LongAdder,ThreadLocalRandom原理. 二.AtomicLong & Lo ...
- POJ2074:Line of Sight——题解
http://poj.org/problem?id=2074 题目大意:(下面的线段都与x轴平行)给两条线段,一个点在其中一条线段看另一条线段,但是中间有很多线段阻挡视线.求在线段上最大连续区间使得在 ...
- 【枚举】 最大子矩阵(I)
题注:最大子矩形问题的解决办法最初由中国国家集训队王知昆前辈整理并发表为论文,在此说明并感谢. Definition 给你一个大矩形,里面有一些障碍点,求一个面积最大的矩形,满足该矩形在大矩形内部且该 ...
- js正则表达式,判断字符串是否以数字组结尾,并取出结尾的数字
js正则表达式,判断字符串是否以数字组结尾,并取出结尾的数字 <!DOCTYPE html> <html> <head> <meta charset=&quo ...
- 仅此一文让你明白ASP.NET MVC 之Model的呈现
本文目的 我们来看一个小例子,在一个ASP.NET MVC项目中创建一个控制器Home,只有一个Index: public class HomeController : Controller { pu ...
- ACE主动对象模式(2)
转载于:http://www.cnblogs.com/TianFang/archive/2006/12/12/590153.html 我们简单的介绍了一下ACE主动对象实现方式,同时提出了两个问题: ...
- Going Home POJ - 2195 费用流板子题
On a grid map there are n little men and n houses. In each unit time, every little man can move one ...
- [zabbix]zabbix分区表操作步骤
Q&A: 1.mul key: . 如果Key是空的, 那么该列值的可以重复, 表示该列没有索引, 或者是一个非唯一的复合索引的非前导列 . 如果Key是PRI, 那么该列是主键的组成部分 . ...