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 ...
随机推荐
- Kafka集群无法外网访问问题解决攻略
Kafka无法集群外网访问问题解决方法 讲解本地消费者和生产者无法使用远程Kafka服务器的处理办法 服务搭建好Kafka服务后,机本.测试 OK,外面机器却无法访问,很是怪异. 环境说明: Ka ...
- mysql中一些表选项
表选项列表 表选项就是,创建一个表的时候,对该表的整体设定,主要有如下几个: charset = 要使用的字符编码, engine = 要使用的存储引擎(也叫表类型), auto_increment ...
- 虚拟机中安装 centOS,本地安装 SSH 连接 - 02
先进入 centOS 中,查询虚拟机的 IP 地址: 双击打开 SSH 可视化客户端: 点击 Connect 需要输入之前那个[无论如何都要使用]的密码. 密码在[centOS - 01]里面设置过, ...
- 【EF】Entity Framework Core 软删除与查询过滤器
本文翻译自<Entity Framework Core: Soft Delete using Query Filters>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 注意 ...
- 【Python】Python基础教程系列目录
Python是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. 在现在的工作及开发当中,Python的使用越来越广泛,为了方便大家的学习,Linux大学 特推出了 <Python基 ...
- P4169 [Violet]天使玩偶/SJY摆棋子
题目背景 感谢@浮尘ii 提供的一组hack数据 题目描述 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅 ...
- 具体数学斯特林数-----致敬Kunth
注意这里讲的是斯特林数而非斯特林公式. 斯特林数分两类:第一类斯特林数 和 第二类斯特林数. 分别记为. 首先描述第二类斯特林数. 描述为:将一个有n件物品的集合划分成k个非空子集的方法数. 比如集合 ...
- 【Revit API】Revit读取当前rvt的所有视图与其名称
1)读取所有视图: public static ViewSet GetAllViews(Document doc) { ViewSet views = new ViewSet(); FilteredE ...
- mysql权限管理,用户管理
1 创建用户 mysql> truncate table user; //先删除所有用户 mysql> CREATE USER 'paris'@'localhost' IDENTIFIE ...
- 浴谷八连测R6题解(收获颇丰.jpg)
这场的题都让我收获颇丰啊QWQ 感谢van♂老师 T1 喵喵喵!当时以为经典题只能那么做, 思维定势了... 因为DP本质是通过一些条件和答案互相递推的一个过程, 实际上就是把条件和答案分配在DP的状 ...