题目链接: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自动机的更多相关文章

  1. HDU 6096 String (AC自动机)

    题意:给出n个字符串和q个询问,每次询问给出两个串 p 和 s .要求统计所有字符串中前缀为 p 且后缀为 s (不可重叠)的字符串的数量. 析:真是觉得没有思路啊,看了官方题解,真是好复杂. 假设原 ...

  2. 2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6138 题意:给n个串,每次询问x号串和y号串的最长公共子串的长度,这个子串必须是n个串中某个串的前缀 ...

  3. 2017多校第9场 HDU 6170 Two strings DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6170 题意:给了2个字符串,其中第2个字符串包含.和*两种特别字符,问第二个字符串能否和第一个匹配. ...

  4. 2017多校第9场 HDU 6161 Big binary tree 思维,类似字典树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6161 题意: 题目是给一棵完全二叉树,从上到下从左到右给每个节点标号,每个点有权值,初始权值为其标号, ...

  5. 2017多校第9场 HDU 6169 Senior PanⅡ 数论,DP,爆搜

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6169 题意:给了区间L,R,求[L,R]区间所有满足其最小质数因子为k的数的和. 解法: 我看了这篇b ...

  6. 2017多校第10场 HDU 6181 Two Paths 次短路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181 题意:给一个图,求出次短路. 解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证 ...

  7. 2017多校第10场 HDU 6180 Schedule 贪心,multiset

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6180 题意:给了一些任务的开始时间和终止时间,现在让我们安排k台及机器,让这些任务在k太机器上最小,并 ...

  8. 2017多校第10场 HDU 6178 Monkeys 贪心,或者DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6178 题意:给出一棵有n个节点的树,现在需要你把k只猴子放在节点上,每个节点最多放一只猴子,且要求每只 ...

  9. 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...

随机推荐

  1. BZOJ4071 & 洛谷3644 & UOJ112:[APIO2015]巴邻旁之桥——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4071 https://www.luogu.org/problemnew/show/P3644 ht ...

  2. BZOJ1208:[HNOI2004]宠物收养所——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1208 Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物 ...

  3. sd卡的访问

    一般再访问sd卡前都要获取sd卡的路径,以防止不同的厂商有不同的路径配置.Android提供了Environment类来获取系统当前sd卡路径. Log.d(TAG, Environment.getE ...

  4. 差点AFO

    差点就AFO了,小伙伴们一定注意护眼啊. 眼睛总算是活过来了. 还有一个月联赛,加油

  5. git使用笔记(十一)rebase

    By francis_hao    Oct 22,2017   git-rebase,改变commit的基础参照 概要 git rebase [-i | --interactive] [options ...

  6. 基于Node.js+MySQL开发的开源微信小程序B2C商城(页面高仿网易严选)

    界面高仿网易严选商城(主要是2016年wap版) 测试数据采集自网易严选商城 功能和数据库参考ecshop 服务端api基于Node.js+ThinkJS+MySQL 计划添加基于Vue.js的后台管 ...

  7. 在CentOS6.5 下安装并使用Java开发opencv的配置(一)

    1) 安装gcc以及cmake等等乱七八糟的软件 yum install gcc yum install python yum install cmake yum groupinstall " ...

  8. [ 转载]Tomcat7 catalina.out 日志分割

    http://m.blog.csdn.net/blog/mark_qi/8864644 最近由于工作需要,tomcat 的catalina.out文件的不断扩大,导致系统磁盘空间边变小,而且管理也难于 ...

  9. [技巧篇]14.据说SSH框架需要的监听器,IntrospectorCleanupListener

    开发这么久,我也没有使用过IntrospectorCleanupListener监听器,今天偶尔看到一篇文章,虽然没有怎么读懂,也不太理解,但是好像给官方提供一些解释!给自己留一个备注,多点东西因为没 ...

  10. Spring实战第一部分总结

                                                         Spring实战第一部分总结 第一章 综述 1. DI依赖注入让相互协作的组件保持松散耦合,而 ...