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 ...
随机推荐
- c 读取文本
#include <stdio.h> #include <stdlib.h> #include <string.h> #define max 10 #define ...
- gridview 第一行编辑
<%@ Page Language="C#" AutoEventWireup="true" Codebehind="Default.aspx.c ...
- p2 休眠模式
如有错误,忘请指出. 才入手p2.p2有全局休眠模式,和钢体体眠模式.钢体能控制 body.allowSleep world.NO_SLEEPING 不允许休眠world.BODY_SLEEPING ...
- Linux服务器开启tomcat的gc日志
压力测试,为了能监控长期对gc的变化的情况,那么就需要在tomcat中进行配置相关的gc输入日志,以便后续来对gc中进行分析 工具 :linux+tomcat 1.进入到了tomcat的bin的目录下 ...
- ZOJ2686_Cycle Gameu
题目的意思是给你一个多边形,每条边上有一个权值,你开始在第一个点.每次你必须经过一条有权值的边,并且把该边的权值减小到任意一个非负值,到达该边的另外一个点. 谁第一个无法操作就算输. 题意很简单,解法 ...
- 洛谷 P1344 [USACO4.4]追查坏牛奶Pollutant Control
题目描述 你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶.很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网.这个送货网很大,而且关系复杂.你知道这批牛 ...
- 浅谈Android发展趋势分析
去年11月16.17日,我有幸参加了北京2017安卓技术大会,做了关于车载Android系统的演讲,并主持了诸多大咖参与的圆桌讨论,对Android未来几年的发展趋势进行了一番讨论.来自小米.百度.高 ...
- 【BZOJ1491】【NOI2007】社交网络(最短路,动态规划)
[BZOJ1491][NOI2007]社交网络(最短路,动态规划) 题面 BZOJ 洛谷 图片是假的,只能到OJ上看 Description 在社交网络(socialnetwork)的研究中,我们常常 ...
- Linux内核分析第七周学习笔记——Linux内核如何装载和启动一个可执行程序
Linux内核分析第七周学习笔记--Linux内核如何装载和启动一个可执行程序 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study. ...
- VS2010中使用Github进行版本控制【补充】
http://blog.csdn.net/softwave/article/details/8499264 前面我在文章<VS2010结合Github进行版本控制>中介绍了VS 2010中 ...