zoukankan      html  css  js  c++  java
  • 题解 SP1812 【LCS2

    对于本题这样的多字符串的子串匹配问题,其实用广义后缀自动机就可以很好的解决,感觉会比普通的后缀自动机做法方便一些。

    首先记录出每个节点被多少个字符串更新,也就是记录每个节点有多少个字符串能到达它,可以通过在(Parent)树上求子树和处理出。

    若所有字符串都能到达一个节点,也就是该节点所对应的串为所有字符串的子串,那么该节点是一个合法的转移状态。

    那么就可以直接拿这些字符串中的任意一个字符串在自动机上匹配,就像LCS - Longest Common Substring一样,只向合法状态转移,记录当前匹配出的最长公共子串的最大长度即可。

    实现细节看代码吧。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 2000010
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,las,tot=1,root=1,num,ans;
    int fa[maxn],len[maxn],ch[maxn][30],siz[maxn][12];
    char s[maxn];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]=(edge){to,head[from]};
        head[from]=edge_cnt;
    }
    void insert(int c,int id)
    {
        int p=las,np=las=++tot;
        len[np]=len[p]+1,siz[np][id]++;
        while(p&&!ch[p][c]) ch[p][c]=np,p=fa[p];
        if(!p) fa[np]=root;
        else
        {
            int q=ch[p][c];
            if(len[q]==len[p]+1) fa[np]=q;
            else
            {
                int nq=++tot;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                len[nq]=len[p]+1,fa[nq]=fa[q],fa[q]=fa[np]=nq;
                while(ch[p][c]==q) ch[p][c]=nq,p=fa[p];
            }
        }
    }
    void dfs(int x)
    {
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            dfs(y);
            for(int id=1;id<=num;++id)
                siz[x][id]+=siz[y][id];
        }
    }
    bool check(int p)
    {
        if(!p) return false;
        for(int i=1;i<=num;++i)
            if(!siz[p][i])
                return false;
        return true;
    }
    void work()
    {
        for(int i=2;i<=tot;++i) add(fa[i],i);
        dfs(root);
        int p=root,l=0;
        for(int i=1;i<=n;++i)
        {
            int c=s[i]-'a';
            if(check(ch[p][c])) l++,p=ch[p][c];
            else
            {
                while(p&&!check(ch[p][c])) p=fa[p];
                if(p) l=len[p]+1,p=ch[p][c];
                else l=0,p=root;
            }
            ans=max(ans,l);
        }
    }
    int main()
    {
        while(scanf("%s",s+1)!=EOF)
    	{
    		n=strlen(s+1),las=root,num++;
    		for(int i=1;i<=n;++i) insert(s[i]-'a',num);
    	}
        work(),printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Ternsorflow 学习:002-Tensorflow 基础知识
    Ternsorflow 学习:001-通过例程,初步了解Tensorflow
    Wpa_supplicant 调试故障原因分析
    Ternsorflow 学习:000-在 Ubuntu 16.04 上安装并使用 TensorFlow_v1.14 (改)
    开发工具类(eclipse、安卓SDK) 镜像站
    Linux镜像源 国内列表
    linux桌面系统 镜像下载
    arm linux 移植 udhcp 与 使用
    Docker三剑客之compose
    Docker基础内容之端口映射
  • 原文地址:https://www.cnblogs.com/lhm-/p/12460847.html
Copyright © 2011-2022 走看看