zoukankan      html  css  js  c++  java
  • 题解 洛谷 P4112 【[HEOI2015]最短不公共子串】

    给定两个字符串(A)(B),我们需要找出一个串,其在(A)中出现且不在(B)中出现,这个串为子串或者子序列,求在每种情况下,该串的最短长度。

    考虑到后缀自动机可以识别一个字符串的所有子串,序列自动机可以识别一个字符串的所有子序列。

    那么我们直接对(A)(B)两个字符串建出相应的自动机,在两个自动机上同时进行(bfs),当发现存在一个串在(A)上可识别,在(B)上无法识别,那么就找到了答案,若(bfs)整个过程结束了,说明没有符合要求的答案,直接返回(-1)

    具体实现细节看代码吧。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 4010
    using namespace std;
    char s1[maxn],s2[maxn];
    struct Automata
    {
        int root,tot,las;
        int len[maxn],ch[maxn][30],fa[maxn],last[30];
        void clear_sam()
        {
            tot=las=root=1;
            memset(fa,0,sizeof(fa));
            memset(ch,0,sizeof(ch));
            memset(len,0,sizeof(len));
        }
        void clear_seq()
        {
            root=2010;
            memset(ch,0,sizeof(ch));
            memset(last,0,sizeof(last));
        }
        void insert(int c)
        {
            int p=las,np=las=++tot;
            len[np]=len[p]+1;
            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[np]=fa[q]=nq;
                    while(ch[p][c]==q) ch[p][c]=nq,p=fa[p];
                }
            }
        }
        void sam(char *s)
        {
            clear_sam();
            int lenth=strlen(s+1);
            for(int i=1;i<=lenth;++i) insert(s[i]-'a'+1);
        }
        void seq(char *s)
        {
            clear_seq();
            int lenth=strlen(s+1);
            for(int i=lenth;i;--i)
            {
                for(int j=1;j<=26;++j) ch[i][j]=last[j];
                last[s[i]-'a'+1]=i;
            }
            for(int i=1;i<=26;++i) ch[root][i]=last[i];
        }
    }A,B;
    struct node
    {
        int a,b,len;
    };
    bool vis[maxn][maxn];
    int query()
    {
        memset(vis,0,sizeof(vis));    
        queue<node> q;
        q.push((node){A.root,B.root,0});
        vis[A.root][B.root]=true;
        while(!q.empty())
        {
            node now=q.front();
            q.pop();
            for(int i=1;i<=26;++i)
            {
                int a=A.ch[now.a][i],b=B.ch[now.b][i];
                if(vis[a][b]) continue;
                if(a&&!b) return now.len+1;
                vis[a][b]=true;
                q.push((node){a,b,now.len+1});
            }
        }
        return -1;
    }
    int main()
    {
    	scanf("%s%s",s1+1,s2+1);
        A.sam(s1),B.sam(s2),printf("%d
    ",query());
        A.sam(s1),B.seq(s2),printf("%d
    ",query());
        A.seq(s1),B.sam(s2),printf("%d
    ",query());
        A.seq(s1),B.seq(s2),printf("%d
    ",query());
    	return 0;
    }
    
  • 相关阅读:
    写代码随想
    学生管理系统
    自定义栈
    位运算符加密
    自定义Vector
    二叉树排序
    双向循环链表
    双向链表
    加载properties文件
    通讯录
  • 原文地址:https://www.cnblogs.com/lhm-/p/12246606.html
Copyright © 2011-2022 走看看