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与他上下相邻的某个数交换,问最少交换多少次可以 ...
随机推荐
- 【bzoj4903/uoj300】[CTSC2017]吉夫特 数论+状压dp
题目描述 给出一个长度为 $n$ 的序列,求所有长度大于等于2的子序列个数,满足:对于子序列中任意两个相邻的数 $a$ 和 $b$ ($a$ 在 $b$ 前面),${a\choose b}\mod 2 ...
- 【bzoj2259】[Oibh]新型计算机 堆优化Dijkstra
题目描述 Tim正在摆弄着他设计的“计算机”,他认为这台计算机原理很独特,因此利用它可以解决许多难题. 但是,有一个难题他却解决不了,是这台计算机的输入问题.新型计算机的输入也很独特,假设输入序列中有 ...
- 【bzoj4300】绝世好题 dp
题目描述 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len). 输入 输入文件共2行. 第一行包括一个整数n. 第二行包括n个 ...
- Python面向对象—类属性和实例属性
属性:就是属于一个对象的数据或函数元素 类有类方法.实例方法.静态方法.类数据属性(类变量)和实例数据属性(实例变量). 类属性:包括类方法和类变量,可以通过类或实例来访问,只能通过类来修改. 实例属 ...
- 自学Python快速入门
1 helloworld#基本语法print("hello") #换行print('1221312\12312312\2312312321312\21312312') ##表示注释 ...
- 2016多校联合训练1 D题GCD (ST表+二分)
暑假颓废了好久啊...重新开始写博客 题目大意:给定10w个数,10w个询问.每次询问一个区间[l,r],求出gcd(a[l],a[l+1],...,a[r])以及有多少个区间[l',r']满足gcd ...
- bzoj2064: 分裂(集合DP)
......咸鱼了将近一个月,因为沉迷ingress作业越来越多一直没时间搞OI呜呜呜 题目大意:有一个初始集合(n个元素)和一个目标集合(m个元素)(1<=n,m<=10),两个操作 ...
- 自动清理N天前的二进制日志
这里以自动清理5天前的二进制日志为例(做了同步或依赖于二进制日志备份的请慎用): 以root身份登录数据库,执行以下命令: ; 首次设置expire_logs_days参数后需要执行flush log ...
- 使用py-faster-rcnn训练VOC2007数据集时遇到问题
使用py-faster-rcnn训练VOC2007数据集时遇到如下问题: 1. KeyError: 'chair' File "/home/sai/py-faster-rcnn/tools/ ...
- HDU 5646
DZY Loves Partition Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Ot ...