题目链接: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. JS执行上下文(执行环境)详细图解

    JS执行上下文(执行环境)详细图解 先随便放张图 我们在JS学习初期或者面试的时候常常会遇到考核变量提升的思考题.比如先来一个简单一点的. console.log(a); // 这里会打印出什么? v ...

  2. [LOJ #2473] [九省联考2018] 秘密袭击coat

    题目链接 洛谷. LOJ,LOJ机子是真的快 Solution 我直接上暴力了...\(O(n^2k)\)洛谷要\(O2\)才能过...loj平均单点一秒... 直接枚举每个点为第\(k\)大的点,然 ...

  3. [洛谷P3931]SAC E#1 - 一道难题 Tree

    题目大意:给你一棵带权有根树,可以切断一些边,问使得根和叶子节点不连通的最小代价. 题解:做了一天的网络流,这道题显然可以用最小割来做,但是也可以用树形$DP$,基本同[SDOI2011]消耗战,这道 ...

  4. BZOJ5334:[TJOI2018]数学计算——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5334 小豆现在有一个数x,初始值为1. 小豆有Q次操作,操作有两种类型:  1 m: x = x ...

  5. [LNOI] 相逢是问候 || 扩展欧拉函数+线段树

    原题为2017六省联考的D1T3 给出一个序列,m次操作,模数p和参数c 操作分为两种: 1.将[l,r]区间内的每个数x变为\(c^x\) 2.求[l,r]区间内数的和%p 首先,我们要了解一些数论 ...

  6. mac, xcode 6.1 安装command line tools 支持,autoconf,automake等

    以下软件包 都去我的环境库找到 1 先安装 tcl库 2 安装macports /opt/local/bin/port 一般装到这里 安装autoconf时提示: Warning: The Xcode ...

  7. javascript push 和 concat 的区别

    array.push(item1,item2,item3...) array.concat(item1,item2,item3...) 1. push和concat的元素都既可以是普通元素(任意类型) ...

  8. 挖一挖unsigned int和补码

    文章要讨论的是两部分: 1. 原码,反码和补码. 2. short, unsigned short, int, unsigned int, long, unsigned long的表示及转换 1. 原 ...

  9. HDU2031 进制转换

    #include <iostream> #include "string" #include "cstdio" #include "cst ...

  10. redis.conf 配置

    daemonize yes #以后台daemon方式运行redis pidfile "/var/run/redis.pid" #redis以后台运行,默认pid文件路径/var/r ...