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 ...
随机推荐
- 敏捷冲刺DAY6
一. 每日会议 1. 照片 2. 昨日完成工作 3. 今日完成工作 4. 工作中遇到的困难 对于可视控件,是能进行设计的,但是对于不可视组件,比如AdoConnection怎么才能设计.但是我看del ...
- 【第三周】每周psp
代码累计 300+575+475=1250 随笔字数 1700+3000+3785=8485 知识点 Cppunit框架 Ui设计 Scrum站立会议 燃尽图(好像没燃起来) 博客写作技能 本周主要是 ...
- 模板CodeTemplate
/** * @author:dubbo@xxxx.com * @date: ${date} ${time} * @version: V1.0 * @review: dubbo/${date} ${ti ...
- VSVC2010中常用的C++11特性
static_assert 声明 static_assert 声明在编译时测试软件断言,这与在运行时进行测试的其他断言机制不同. 如果断言失败,则编译也将失败,且系统将发出指定的错误消息. const ...
- react-router之代码分离
概念 无需用户下载整个应用之后才能访问访问它.即边访问边下载.因此我们设计一个组件<Bundle>当用户导航到它是来动态加载组件. import loadSomething from 'b ...
- LoadRunner脚本增强技巧之检查点
检查点的设置理解起来非常简单,就是要在服务器返回的页面中检查是否存在关键信息.检查点函数的错误会导致整个脚本运行结果的失败,通过这个功能可以方便地定位脚本运行中的逻辑错误.检查点的设置通常分为两种,一 ...
- POJ 3276 Face The Right Way(前缀和优化)
题意:有长度为N的01串,有一个操作可以选择连续K个数字取反,求最小的操作数和最小的K使得最后变成全1串.(N<=5000) 由于K是不定的,无法高斯消元. 考虑枚举K,求出最小的操作数. 显然 ...
- scoket常用函数简单介绍
scoket: 是一种抽象层,应用程序通过它来发送和接收数据,使用socket可以将应用程序添加到网络中,与处于同一网络中的其他应用程序进行通信. 简单来说,scoket提供了程序内部与外界通道的 ...
- 【Java】POI的HSSFRichTextString介绍
在使用Apache的POI库生成EXCEL文件时,经常会遇到这样的情况:使用不同的格式格式化一个单元格中的内容,比如说:一个单元格的内容是“first, second”,现在要分别使用红色带删除线格式 ...
- Codeforces Round#514 Div.2 翻车记
A:签到 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...