题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6138

题意:给n个串,每次询问x号串和y号串的最长公共子串的长度,这个子串必须是n个串中某个串的前缀

解法1:AC自动机。做法是把n个串建成AC自动机,前缀树中每个节点都当做结尾节点,val赋为trie树深度,然后把x串丢进自动机里,把匹配到的前缀节点染个色,再把y串丢进去,遇到同样颜色的前缀节点就更新一下答案。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int M = 5e5+10;
const int S = 26;
struct AcAutomata{
int root,sz;
int nxt[M][S],fail[M],val[M],col[N];
int newnode(){
val[sz] = col[sz] = 0;
memset(nxt[sz], -1, sizeof(nxt[sz]));
return sz++;
}
void init(){
memset(val, 0, sizeof(val));
sz = 0;
root = newnode();
}
void insert(char *s){
int u=root;
int len=strlen(s);
for(int i=0; i<len; i++){
int id=s[i]-'a';
if(nxt[u][id]==-1) nxt[u][id]=newnode();
val[nxt[u][id]]=val[u]+1;
u=nxt[u][id];
}
}
void build(){
queue <int> q;
fail[root] = root;
for(int i=0; i<S; i++){
int &v = nxt[root][i];
if(~v){
fail[v] = root;
q.push(v);
}
else{
v = root;
}
}
while(q.size()){
int u = q.front(); q.pop();
for(int i = 0; i < S; i++){
int &v = nxt[u][i];
if(~v){
fail[v] = nxt[fail[u]][i];
q.push(v);
}
else{
v = nxt[fail[u]][i];
}
}
}
}
void update(char *s, int x){
int len = strlen(s);
int u=root;
for(int i=0; i<len; i++){
int id=s[i]-'a';
u=nxt[u][id];
int tmp=u;
while(tmp){
col[tmp]=x;
tmp=fail[tmp];
}
}
}
int query(char *s, int x){
int len = strlen(s);
int u = root;
int ans = 0;
for(int i=0; i<len; i++){
int id=s[i]-'a';
u=nxt[u][id];
int tmp=u;
while(tmp){
if(col[tmp]==x) ans=max(ans, val[tmp]);
tmp=fail[tmp];
}
}
return ans;
}
}ZXY;
char s[N];
int pos[N];
int main()
{
int T,n,q;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
ZXY.init();
int d=1;
for(int i=1; i<=n; i++){
pos[i]=d;
scanf("%s", s+d);
ZXY.insert(s+d);
int len=strlen(s+d);
d+=len+1;
}
ZXY.build();
scanf("%d", &q);
int id=1;
while(q--)
{
int x, y;
scanf("%d%d",&x,&y);
ZXY.update(s+pos[x],id);
int ans = ZXY.query(s+pos[y],id);
++id;
printf("%d\n", ans);
}
}
return 0;
}

解法2:KMP,直接枚举n个串做KMP。。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
vector<int> Next[maxn];
string str[maxn];
void getnext(string &s, vector<int> &nxt)
{
int len = s.size();
nxt.resize(len);
nxt[0] = -1;
int i, j = -1;
for(i = 1; i < len; i++)
{
while(j >= 0 && s[j + 1] != s[i])
j = nxt[j];
if(s[j + 1] == s[i])
j++;
nxt[i] = j;
}
}
int getMax(string &s, int strid)
{
int len = s.size();
int i, j = -1;
int ret = 0;
for(i = 0; i < len; i++)
{
while(j >= 0 && str[strid][j + 1] != s[i])
j = Next[strid][j];
if(str[strid][j + 1] == s[i])
j++;
ret = max(ret, j + 1);
}
return ret;
}
char buf[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%s", buf);
str[i] = buf;
getnext(str[i], Next[i]);
}
int q;
scanf("%d", &q);
while(q--)
{
int x, y;
scanf("%d %d", &x, &y);
int ans = 0;
for(int i = 1; i <= n; i++)
{
int u = getMax(str[x], i);
int v = getMax(str[y], i);
ans = max(ans, min(u, v));
}
printf("%d\n", ans);
}
}
return 0;
}

2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP的更多相关文章

  1. 2017多校第8场 HDU 6138 Fleet of the Eternal Throne 思维,暴力

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6138 题意:给了初始区间[-1,1],然后有一些操作,可以r加上一个数,l减掉一个数,或者同时操作,问 ...

  2. HDU 6138 Fleet of the Eternal Throne(后缀自动机)

    题意 题目链接 Sol 真是狗血,被疯狂卡常的原因竟是 我们考虑暴力枚举每个串的前缀,看他能在\(x, y\)的后缀自动机中走多少步,对两者取个min即可 复杂度\(O(T 10^5 M)\)(好假啊 ...

  3. HDU 6138 Fleet of the Eternal Throne(AC自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6138 [题目大意] 给出一些串,询问第x个串和第y个串的公共子串, 同时要求该公共子串为某个串的前 ...

  4. 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 ...

  5. HDU 6138 Fleet of the Eternal Throne 后缀数组 + 二分

    Fleet of the Eternal Throne Problem Description > The Eternal Fleet was built many centuries ago ...

  6. 2017多校第6场 HDU 6096 String AC自动机

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6096 题意:给了一些模式串,然后再给出一些文本串的不想交的前后缀,问文本串在模式串的出现次数. 解法: ...

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

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

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

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

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

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

随机推荐

  1. hdu 3549 Flow Problem (网络最大流)

    Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...

  2. 【题解】HNOI2016网络

    整体二分是个好东西!可我忘记了它QAQ其实当你知道这题可以整体二分的时候就已经不难了(个人觉得这是最难想到的一点啊).整体二分的话,我们就可以把问题转化为是否有一条权值 \(>= k\) 的链经 ...

  3. [洛谷P4592][TJOI2018]异或

    题目大意:有一棵$n$个点的树,第$i$个点权值为$w_i$,有两种操作: $1\;x\;y:$询问节点$x$的子树中与$y$异或结果的最大值 $2\;x\;y\;z:$询问路径$x$到$y$上点与$ ...

  4. LibreOJ #6221. 幂数 !(数论+dfs+剪枝)

    写新题然后艹翻标程的感觉真是舒爽啊... 这题就是个dfs...先预处理出sqrt(n)范围内的素数,然后dfs构造合法的数就行了. 直接暴搜会TLE,需要剪一剪枝,不需要跑到最后一层再计算答案,边构 ...

  5. TYVJ2032 升降梯上

    Description: 开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道.一辆停在轨道底部的电梯.和电梯内一杆控制电梯升降的巨大手柄.Nescafe ...

  6. dubbox管理中心

    当服务多了,不好管理,可以用管理中心来查看. 管理中心就是一个 web项目(一个war包),可以部署在tomcat下面就能运行了. 用户名密码都是root 每一条服务点开后都可以看生产者和消费者.

  7. ACM1829并查集

    A Bug's Life Problem Description Background Professor Hopper is researching the sexual behavior of a ...

  8. liunx系统下安装mysql数据库5.7.13版本

    一:在/usr/local目录下解压安装包

  9. [LeetCode] Simplify Path,文件路径简化,用栈来做

    Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", ...

  10. 给定一个数字n,不用for循环实现输出数组 [1,2,3,4,...,n]

    一.for循环方式实现输出[1, 2, 3, ..., n] var n = 5; function test(n){ var arr=[]; for( var i = 1; i <= n; i ...