2017ACM暑期多校联合训练 - Team 8 1006 HDU 6138 Fleet of the Eternal Throne (字符串处理 AC自动机)
Problem Description
The Eternal Fleet was built many centuries ago before the time of Valkorion by an unknown race on the planet of Iokath. The fate of the Fleet's builders is unknown but their legacy would live on. Its first known action was in the annihilation of all life in Wild Space. It spread across Wild Space and conquered almost every inhabited world within the region, including Zakuul. They were finally defeated by a mysterious vessel known as the Gravestone, a massive alien warship that countered the Eternal Fleet's might. Outfitted with specialized weapons designed to take out multiple targets at once, the Gravestone destroyed whole sections of the fleet with a single shot. The Eternal Fleet was finally defeated over Zakuul, where it was deactivated and hidden away. The Gravestone landed in the swamps of Zakuul, where the crew scuttled it and hid it away.
— Wookieepedia
The major defeat of the Eternal Fleet is the connected defensive network. Though being effective in defensing a large fleet, it finally led to a chain-reaction and was destroyed by the Gravestone. Therefore, when the next generation of Eternal Fleet is built, you are asked to check the risk of the chain reaction.
The battleships of the Eternal Fleet are placed on a 2D plane of n rows. Each row is an array of battleships. The type of a battleship is denoted by an English lowercase alphabet. In other words, each row can be treated as a string. Below lists a possible configuration of the Eternal Fleet.
aa
bbbaaa
abbaababa
abba
If in the x-th row and the y-th row, there exists a consecutive segment of battleships that looks identical in both rows (i.e., a common substring of the x-th row and y-th row), at the same time the substring is a prefix of any other row (can be the x-th or the y-th row), the Eternal Fleet will have a risk of causing chain reaction.
Given a query (x, y), you should find the longest substring that have a risk of causing chain reaction.
Input
The first line of the input contains an integer T, denoting the number of test cases.
For each test cases, the first line contains integer n (n≤10^5).
There are n lines following, each has a string consisting of lower case letters denoting the battleships in the row. The total length of the strings will not exceed 105.
And an integer m (1≤m≤100) is following, representing the number of queries.
For each of the following m lines, there are two integers x,y, denoting the query.
Output
You should output the answers for the queries, one integer per line.
Sample Input
1
3
aaa
baaa
caaa
2
2 3
1 2
Sample Output
3
3
题意:
给出n个字符串,m次询问,每一次询问一个(x,y),问第x和第y个字符串的最长公
共部分并且这个部分是这n个字符串中某一个字符串的前缀。
分析:
注意到如果两个字符串同时匹配到了某一个前缀,那么这个前缀的长度就可以用来更新答案,所以我们可以直接根据前缀建立AC自动机。
建立AC自动机这个最原始的部分就是根据这n个字符串建立一个字典树,这里还是比较好理解的。 AC自动机与字典树的区别就在于AC自动机中有一个fail指针。
fail指针的含义:一个节点的失败指针就是指与这个节点上表示的字符相同,但是在树上的位置要是里这个节点最近的上面的那个节点。
构造失败指针的过程概括起来就一句话:设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,他的儿子中也有字母为C的节点。然后把当前节点的失败指针指向那个字母也为C的儿子。如果一直走到了root都没找到,那就把失败指针指向root。
到这里整个AC自动机也就构造完成了,接下来的任务就是进行模式匹配。
这里与之前的不同点在于不是单纯的两个字符串进行模式匹配,我们在它们匹配的过程中还要使得它们的最长匹配串时某个字符串的前缀。
这里给每个节点增加一个info属性,用来唯一的表示一个节点。 对于每次询问在AC自动机上匹配,用set判断是否被匹配过,我们每次在匹配一个字符串的时候,不仅要保存这个字符串本身,最主要的是找到整个字符串的fail指针,这样我们在set中找的时候,肯定是找的fail指针指向的那一部分,这样的话才能,将前缀匹配串的最大长度找出来。
#include <bits/stdc++.h>
using namespace std;
const int N = 100100;
struct AC_Node///建立AC自动机的结构体
{
int nxt[26],fail,info,len;///当前节点的直接子节点、失败指针、每个节点的一个单独的信息、长度
void init()
{
fill(nxt,nxt+26,0);
fail=info=0;
}
} ac[N];
int id,q[N],pre;
void Insert(const string& s)
{
int now=0,len=s.size();
for(int i=0; i<len; i++)
{
int t=s[i]-'a';
if(ac[now].nxt[t])
now=ac[now].nxt[t];///如果当前的树里面已经有了这个节点
else
{
ac[++id].init();///创建一个新的节点
ac[now].nxt[t]=id;///当前节点的第t个子节点指向这个节点
now=id;///指针往下移动
}
ac[now].info=++pre;
ac[now].len=i+1;///长度
}
}
void Build_fail()///构建树上的每一个节点的失败指针
{
int now,t,head=0,tail=0;
q[tail++]=0;
ac[0].fail=0;///根节点的失败指针肯定是指向自己的
while(head!=tail)
{
now=q[head++];
for(int i=0; i<26; i++)
if(ac[now].nxt[i])
{
for(t=ac[now].fail; t&&!ac[t].nxt[i]; t=ac[t].fail);///t!=0&&a[t].nxt[i]==0时循环
if(now)
ac[ac[now].nxt[i]].fail=ac[t].nxt[i];
q[tail++]=ac[now].nxt[i];
}
}
}
int ans;
set<int>se;
string s;
vector<string>v;
void Search(int x,bool op)
{
int len=v[x].size(),now=0,t,k;
for(int i=0; i<len; i++)
{
t=v[x][i]-'a';
for(; now&&!ac[now].nxt[t]; now=ac[now].fail);///now!=0&&a[now].nxt[t]!=0
now=ac[now].nxt[t];
for(k=now; k; k=ac[k].fail)///在插进去这个字符串的同时也把这个串上涉及到的所有的失败节点插进去了
if(ac[k].info)
{
if(op)
{
se.insert(ac[k].info);
}
else
{
if(se.find(ac[k].info)!=se.end())
ans=max(ans,ac[k].len);
}
}
}
}
int main()
{
int T,n,m,x,y;
scanf("%d",&T);
while(T--)
{
v.clear();///vector容器
id=pre=0;
ac[0].init();///树的根节点的一个初始化过程
scanf("%d",&n);
for(int i=0; i<n; i++)
{
cin>>s;
v.push_back(s);
Insert(s);
}
Build_fail();
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&x,&y);
x--,y--;
ans=0;
se.clear();
Search(x,true);
Search(y,false);
printf("%d\n",ans);
}
}
return 0;
}
2017ACM暑期多校联合训练 - Team 8 1006 HDU 6138 Fleet of the Eternal Throne (字符串处理 AC自动机)的更多相关文章
- 2017ACM暑期多校联合训练 - Team 5 1006 HDU 5205 Rikka with Graph (找规律)
题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...
- 2017ACM暑期多校联合训练 - Team 2 1006 HDU 6050 Funny Function (找规律 矩阵快速幂)
题目链接 Problem Description Function Fx,ysatisfies: For given integers N and M,calculate Fm,1 modulo 1e ...
- 2017ACM暑期多校联合训练 - Team 1 1006 HDU 6038 Function (排列组合)
题目链接 Problem Description You are given a permutation a from 0 to n−1 and a permutation b from 0 to m ...
- 2017ACM暑期多校联合训练 - Team 4 1004 HDU 6070 Dirt Ratio (线段树)
题目链接 Problem Description In ACM/ICPC contest, the ''Dirt Ratio'' of a team is calculated in the foll ...
- 2017ACM暑期多校联合训练 - Team 9 1005 HDU 6165 FFF at Valentine (dfs)
题目链接 Problem Description At Valentine's eve, Shylock and Lucar were enjoying their time as any other ...
- 2017ACM暑期多校联合训练 - Team 9 1010 HDU 6170 Two strings (dp)
题目链接 Problem Description Giving two strings and you should judge if they are matched. The first stri ...
- 2017ACM暑期多校联合训练 - Team 8 1002 HDU 6134 Battlestation Operational (数论 莫比乌斯反演)
题目链接 Problem Description The Death Star, known officially as the DS-1 Orbital Battle Station, also k ...
- 2017ACM暑期多校联合训练 - Team 8 1011 HDU 6143 Killer Names (容斥+排列组合,dp+整数快速幂)
题目链接 Problem Description Galen Marek, codenamed Starkiller, was a male Human apprentice of the Sith ...
- 2017ACM暑期多校联合训练 - Team 8 1008 HDU 6140 Hybrid Crystals (模拟)
题目链接 Problem Description Kyber crystals, also called the living crystal or simply the kyber, and kno ...
随机推荐
- 软工网络15团队作业4——Alpha阶段敏捷冲刺-7
一.当天站立式会议照片: 二.项目进展 昨天已完成的工作: 进一步优化功能与完善服务器. 明天计划完成的工作: 服务器是需要完善,后端的配置还需要修改. 工作中遇到的困难: 今日遇到的困难是服务器后端 ...
- 2."结对项目"的心得体会
上个星期,老师给我们布置了个课堂小作业: 某公司程序员二柱的小孩上了小学二年级,老师让家长每天出30道(100以内)四则运算题目给小学生做.二柱立马就想到写一个小程序来做这件事. 这个事情可以用很 ...
- maven Web项目中POM的配置信息
什么是POM? POM是项目对象模型(Project Object Model)的简称,它是Maven项目中的文件,使用XML表示,名称叫做pom.xml.在Maven中,当谈到Project的时候, ...
- 第113天:Ajax跨域请求解决方法
一.原生JS实现ajax 第一步获得XMLHttpRequest对象 第二步:设置状态监听函数 第三步:open一个连接,true是异步请求 第四部:send一个请求,可以发送一个对象和字符串,不需要 ...
- 25个Java机器学习工具&库--转载
本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...
- [十六]SpringBoot 之 读取环境变量和绑定属性对象
1.读取环境变量 凡是被spring管理的类,实现接口EnvironmentAware 重写方法 setEnvironment 可以在工程启动时,获取到系统环境变量和application配置文件中的 ...
- P2169 正则表达式
题目背景 小Z童鞋一日意外的看到小X写了一个正则表达式的高级程序,这个正则表达式程序仅仅由字符“0”,“1”,“.”和“*”构成,但是他能够匹配出所有在OJ上都AC的程序的核心代码!小Z大为颇感好奇, ...
- SQL注入9种绕过WAF方法
SQL注入9种绕过WAF方法 0x01前言 WAF区别于常规 防火墙 是因为WAF能够过滤特定Web应用程序的内容,而常规防火墙则充当服务器之间的防御门.通过检查HTTP的流量,它可以防御Web应用安 ...
- 最近公共祖先(LCA)(题目)
Time Limit: 2000 ms Memory Limit: 256 MB Description Input Output Sample Input 15 5 1 2 3 4 5 6 7 8 ...
- python基础----继承与派生、组合、接口与归一化设计、抽象类、子类中调用父类方法
一.什么是继承 继承是一种创建新的类的方式,在pyth ...