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

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

【题目大意】

  给出一些串,询问第x个串和第y个串的公共子串,
  同时要求该公共子串为某个串的前缀。求最长符合要求的答案

【题解】

  我们对所有串构建AC自动机,将两个询问串之一在AC自动机上mark所有的匹配位置
  另一个串在mark的地方寻找最长匹配即可

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=100010;
int ans;
namespace AC_DFA{
    const int Csize=27;
    int tot,son[N][Csize],sum[N],fail[N],q[N],dph[N],vis[N];
    void Initialize(){
        memset(dph,0,sizeof(int)*(tot+1));
        memset(fail,0,sizeof(int)*(tot+1));
        memset(sum,0,sizeof(int)*(tot+1));
        for(int i=0;i<=tot;i++)for(int j=0;j<Csize;j++)son[i][j]=0;
        tot=0; fail[0]=-1;
    }
    inline int Tr(char ch){return ch-‘a‘;}
    int Insert(char *s){
        int x=0;
        for(int l=strlen(s),i=0,w;i<l;i++){
            if(!son[x][w=Tr(s[i])]){
                son[x][w]=++tot;
                dph[tot]=i+1;
            }x=son[x][w];
        }sum[x]++;
        return x;
    }
    void MakeFail(){
        int h=1,t=0,i,j,x;
        for(i=0;i<Csize;i++)if(son[0][i])q[++t]=son[0][i];
        while(h<=t)for(x=q[h++],i=0;i<Csize;i++)
        if(son[x][i]){
            fail[son[x][i]]=son[fail[x]][i],q[++t]=son[x][i];
        }else son[x][i]=son[fail[x]][i];
    }
    void Cal(char *s){
        memset(vis,0,sizeof(vis));
        for(int l=strlen(s),i=0,x=0,w;i<l;i++){
            while(!son[x][Tr(s[i])])x=fail[x];
            x=son[x][Tr(s[i])];
            for(int j=x;j;j=fail[j])vis[j]=1;
        }
    }
    void Find(char *s){
        for(int l=strlen(s),i=0,x=0,w;i<l;i++){
            while(!son[x][Tr(s[i])])x=fail[x];
            x=son[x][Tr(s[i])];
            for(int j=x;j;j=fail[j])if(vis[j])ans=max(ans,dph[j]);
        }
    }
}
char s[110][N];
int T,n;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        using namespace AC_DFA;
        Initialize();
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]);
            Insert(s[i]);
        }int q;
        MakeFail();
        scanf("%d",&q);
        while(q--){
            int x,y; ans=0;
            scanf("%d%d",&x,&y);
            Cal(s[x]); Find(s[y]);
            printf("%d\n",ans);
        }
    }return 0;
}
时间: 2024-10-10 16:29:32

HDU 6138 Fleet of the Eternal Throne(AC自动机)的相关文章

2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP

题目链接: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 s

hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】

hdu 5955 Guessing the Dice Roll [AC自动机+高斯消元] 题意:给出 n≤10 个长为 L≤10 的串,每次丢一个骰子,先出现的串赢,问获胜概率. 题解:裸的AC自动机,求匹配到终止结点的概率,用 高斯消元?一开始不知道怎么建方程组,直接举个例子吧: Input: 1 2 2 1 1 2 1 图解: x0原本概率就是1,然后还要加上其他结点走向它的概率,,这样最后算下来是大于1的,现在还是觉得怪怪的... 1 #include <cstdio> 2 #inclu

HDU 2243 考研路茫茫――单词情结 (AC自动机 + dp)

HDU 2243 考研路茫茫――单词情结 题意:给定一些词根,如果一个单词包含有词根,则认为是有效的.现在问长度不超过L的单词里面,有多少有效的单词? 思路:这道题和POJ 2778是同样的思路.POJ 2778是要找出长度为L的单词里面有多少无效的单词.那么根据同样的方法构造矩阵,然后所有无效的单词个数为 A + A^2 + ... + A^l 个.而所有单词的个数为26 + 26^2 + - + 26^l 个.两个减一下即为答案. 矩阵连乘求和:I + A^2 + A^3 + ... + A

HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)

题目链接 错的上头了... 这题是DNA的加强版,26^1 +26^2... - A^1-A^2... 先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法.剩下就是各种模板,各种套. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <algorithm> #include <vector> #include &l

Fleet of the Eternal Throne HDU6138

不知道为什么今天晚上神经病,一直睡不着,挣扎了四个多小时,还是决定起来搞点东西,就补了一题:A了之后对比了一下标程似乎更优化~~~快了6倍多代码也很短~ 思路:对所有子串建立AC自动机,然后只需要定义两个数组,一个是每个节点的父亲,一个是每组字符串的最后一个字符的节点标号,然后就顺着每一个x串的fail指针去标记一下,然后顺着y串的fail去搜,搜到标记过的,就更新一下当前最大就好,然后就是结果了,复杂度O(n): 代码: #include <cstdio> #include <algo

hdu 3065病毒侵袭持续中(ac自动机)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3065 中文题题意不解释了. 依旧稍微改一下ac自动机模版就能过了.还有一个坑点!是多组数据!!! #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int M = 5e4 + 10 , MM = 2e6 + 10

HDU 3065 病毒侵袭持续中(AC自动机)

解题思路: 跟上一题类似,仍然是AC自动机的简单应用,记录一下每个串出现的次数即可.. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <vector> #include <queue> #include <str

HDU 5069 Harry And Biological Teacher(AC自动机+线段树)

题意 给定 \(n\) 个字符串,\(m\) 个询问,每次询问 \(a\) 字符串的后缀和 \(b\) 字符串的前缀最多能匹配多长. \(1\leq n,m \leq 10^5\) 思路 多串匹配,考虑 \(\text{AC}\)自动机,对 \(n\) 个串建自动机,观察这个结构,不难发现 \(Trie\) 树的结构和前缀有关,\(fail\) 树的结构和后缀有关. 考虑离线,对于每个 \(b\) ,存储它对应的 \(a\) ,我们通过在自动机上扫 \(b\) 来回答.由于扫到某节点 \(u\)

hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <231)的单词中至少含有一个词根的单词个数:结果mod 264. 基础:poj 2778DNA 序列求的是给定长度不含模式串的合法串的个数:串长度相当,都到了int上界了: 1.mod 264直接使用unsigned long long自然溢出即可:说的有些含蓄..并且也容易想到是直接使用内置类型,要不然高精度的