题目链接: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. [ZJOJ2007]时态同步 贪心

    不是很懂为什么luogu标签是树形DP,感觉我想的就是一个贪心啊... 随机造几组数据,我们发现贪心的确可以得到最优解,那么为什么呢? 假设将所有时态贪心的调整是对的,那么如果一个节点的各个儿子时态不 ...

  2. TCP中三次握手建立和四次握手释放以及相关问题

    本文基于个人所学和网上博文所整理,若有不妥处,欢迎留言指出 TCP连接过程中标志位的意义: 字符缩写 描述 SYN 同步序号,表示此报文是一个连接请求或连接接受报文 ACK 确认位,对接收到的报文的确 ...

  3. [Leetcode] search in rotated sorted array 搜索旋转有序数组

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e.,0 1 2 4 5 6 7might ...

  4. jquery Promise和ES6 Promise的区别

    1. Deferred对象有resolve和reject方法,可以直接修改状态 jquery用Deferred实现了Promise规范,Deferred与ES6 Promise的最大区别是: Defe ...

  5. 剑桥offer(11~20)

    11.题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. class Solution { public: int NumberOf1(int n) { ; unsigned ...

  6. 深入JavaScript对象创建的细节

    最近深入学习javascript后,有个体会:面向对象的方式编程才是高效灵活的编程,也是现在唯一可以让代码更加健壮的编程方式.如果我们抛开那些玄乎的抽象出类等等思想,我自己对面向对象的从写程序的角度理 ...

  7. HDU 1596 floyd

    find the safest road Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  8. 打开cmd窗口新技巧get

    1.在当前目录下,按住shift键+点击右键,选择在此处打开命令窗口 很多时候我们需要打开命令行然后进入到相应目录进行一些操作. 常规的做法是: Win+R打开运行窗口 输入"cmd&quo ...

  9. 使用 Rational AppScan 保证 Web 应用的安全性,第 1 部分: Web 安全与 Rational AppScan 入门

    前言 当今世界,Internet(因特网)已经成为一个非常重要的基础平台,很多企业都将应用架设在该平台上,为客户提供更为方便.快捷的服务支持.这些应用 在功能和性能上,都在不断的完善和提高,然而在非常 ...

  10. xml 通过正则抓取字段

    $str = '<xml> <appid><![CDATA[wxd49ea66070209a6e]]></appid> <bank_type> ...