Fleet of the Eternal Throne HDU6138

不知道为什么今天晚上神经病,一直睡不着,挣扎了四个多小时,还是决定起来搞点东西,就补了一题:A了之后对比了一下标程似乎更优化~~~快了6倍多代码也很短~

思路:对所有子串建立AC自动机,然后只需要定义两个数组,一个是每个节点的父亲,一个是每组字符串的最后一个字符的节点标号,然后就顺着每一个x串的fail指针去标记一下,然后顺着y串的fail去搜,搜到标记过的,就更新一下当前最大就好,然后就是结果了,复杂度O(n);

代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=1e5+10;
struct Trie
{
    int next[maxn][26],fail[maxn],f[maxn],dep[maxn],pos[maxn];
    bool vis[maxn];
    int root,L;
    int newnode()
    {
        for(int i = 0;i < 26;i++)
            next[L][i] = -1;
        L++;
        return L-1;
    }
    void init()
    {
        L = 0;
        dep[0]=0;
        f[0]=0;
        root = newnode();
    }
    void insert(char buf[],int k)
    {
        int len = strlen(buf);
        int now = root;
        for(int i = 0;i < len;i++)
        {
            if(next[now][buf[i]-'a'] == -1)
            {
                next[now][buf[i]-'a'] = newnode();
                dep[next[now][buf[i]-'a']]=dep[now]+1;
                f[next[now][buf[i]-'a']]=now;
            }
            now = next[now][buf[i]-'a'];
        }
        pos[k]=now;
    }
    void build()
    {
        queue<int>q;
        fail[0] = 0;
        for(int i = 0;i < 26;i++)
            if(next[0][i] == -1)
                next[0][i] = 0;
            else
            {
                fail[next[0][i]] = 0;
                q.push(next[0][i]);
            }
        while(!q.empty())
        {
            int now = q.front();q.pop();
            for(int i = 0;i < 26;i++)
            {
                int u=next[now][i];
                if(u == -1)
                    next[now][i] = next[fail[now]][i];
                else
                {
                    fail[u]=next[fail[now]][i];
                    q.push(u);
                }
            }
        }
    }
    int check(int x,int y)
    {
        memset(vis,0,(L+10)*sizeof (bool));
        for(int i=pos[x];i!=0;i=f[i])
            for(int p=i;p!=0;p=fail[p])
                vis[p]=1;
        int M=0;
        for(int i=pos[y];i!=0;i=f[i])
            for(int p=i;p!=0;p=fail[p])
                if(vis[p])M=max(M,dep[p]);
        return M;
    }
};
char buf[100005];
Trie ac;
int main()
{
    freopen("input.txt","r",stdin);
    int T,n,m;
    scanf("%d",&T);
    while( T-- )
    {
        scanf("%d",&n);
        ac.init();
        for(int i = 1;i <= n;i++)
        {
            scanf("%s",buf);
            ac.insert(buf,i);
        }
        ac.build();
        scanf("%d",&m);
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
",ac.check(x,y));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/MeowMeowMeow/p/7393541.html