1. 程式人生 > >【BZOJ4032】[HEOI2015]最短不公共子串(後綴自動機,序列自動機)

【BZOJ4032】[HEOI2015]最短不公共子串(後綴自動機,序列自動機)

公共子串 com 構建 同時存在 ast can class ble print

【BZOJ4032】[HEOI2015]最短不公共子串(後綴自動機,序列自動機)

題面

BZOJ
洛谷

題解

數據範圍很小,直接暴力構建後綴自動機和序列自動機,然後直接在兩個自動機上進行\(bfs\),找到的第一個不同時存在的節點就直接輸出就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MAX 4040
struct SAM
{
    struct Node{int son[26],ff,len;}t[MAX];
    int tot,last;void init(){tot=last=1;}
    void extend(int c)
    {
        int p=last,np=++tot;last=tot;
        t[np].len=t[p].len+1;
        while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff;
        if(!p)t[np].ff=1;
        else
        {
            int q=t[p].son[c];
            if(t[q].len==t[p].len+1)t[np].ff=q;
            else
            {
                int nq=++tot;
                t[nq]=t[q];t[nq].len=t[p].len+1;
                t[q].ff=t[np].ff=nq;
                while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff;
            }
        }
    }
}A,B;
struct SQAM
{
    struct Node{int son[26];}t[MAX];
    int lst[26],pre[MAX],tot,last;
    void init(){tot=last=1;for(int i=0;i<26;++i)lst[i]=1;}
    void extend(int c)
    {
        int p=lst[c],np=++tot;
        pre[np]=p;
        for(int i=0;i<26;++i)
            for(int j=lst[i];j&&!t[j].son[c];j=pre[j])
                t[j].son[c]=np;
        lst[c]=np;
    }
}AA,BB;
char SA[MAX],SB[MAX];
int na,nb;
struct Node{int len,a,b;};
bool vis[MAX][MAX];
int bfs1(SAM &A,SAM &B)
{
    queue<Node> Q;Q.push((Node){0,1,1});
    memset(vis,0,sizeof(vis));vis[1][1]=true;
    while(!Q.empty())
    {
        Node p=Q.front();Q.pop();
        for(int i=0;i<26;++i)
        {
            int x=A.t[p.a].son[i];
            int y=B.t[p.b].son[i];
            if(x&&y)
            {
                if(vis[x][y])continue;
                vis[x][y]=true;Q.push((Node){p.len+1,x,y});
            }
            if(x&&!y)return p.len+1;
        }
    }
    return -1;  
}
int bfs2(SAM &A,SQAM &B)
{
    queue<Node> Q;Q.push((Node){0,1,1});
    memset(vis,0,sizeof(vis));vis[1][1]=true;
    while(!Q.empty())
    {
        Node p=Q.front();Q.pop();
        for(int i=0;i<26;++i)
        {
            int x=A.t[p.a].son[i];
            int y=B.t[p.b].son[i];
            if(x&&y)
            {
                if(vis[x][y])continue;
                vis[x][y]=true;Q.push((Node){p.len+1,x,y});
            }
            if(x&&!y)return p.len+1;
        }
    }
    return -1;  
}
int bfs3(SQAM &A,SAM &B)
{
    queue<Node> Q;Q.push((Node){0,1,1});
    memset(vis,0,sizeof(vis));vis[1][1]=true;
    while(!Q.empty())
    {
        Node p=Q.front();Q.pop();
        for(int i=0;i<26;++i)
        {
            int x=A.t[p.a].son[i];
            int y=B.t[p.b].son[i];
            if(x&&y)
            {
                if(vis[x][y])continue;
                vis[x][y]=true;Q.push((Node){p.len+1,x,y});
            }
            if(x&&!y)return p.len+1;
        }
    }
    return -1;  
}
int bfs4(SQAM &A,SQAM &B)
{
    queue<Node> Q;Q.push((Node){0,1,1});
    memset(vis,0,sizeof(vis));vis[1][1]=true;
    while(!Q.empty())
    {
        Node p=Q.front();Q.pop();
        for(int i=0;i<26;++i)
        {
            int x=A.t[p.a].son[i];
            int y=B.t[p.b].son[i];
            if(x&&y)
            {
                if(vis[x][y])continue;
                vis[x][y]=true;Q.push((Node){p.len+1,x,y});
            }
            if(x&&!y)return p.len+1;
        }
    }
    return -1;  
}
int main()
{
    scanf("%s%s",SA+1,SB+1);
    na=strlen(SA+1);nb=strlen(SB+1);
    A.init();B.init();AA.init();BB.init();
    for(int i=1;i<=na;++i)A.extend(SA[i]-97);
    for(int i=1;i<=nb;++i)B.extend(SB[i]-97);
    for(int i=1;i<=na;++i)AA.extend(SA[i]-97);
    for(int i=1;i<=nb;++i)BB.extend(SB[i]-97);
    printf("%d\n%d\n%d\n%d\n",bfs1(A,B),bfs2(A,BB),bfs3(AA,B),bfs4(AA,BB));
    return 0;
}

【BZOJ4032】[HEOI2015]最短不公共子串(後綴自動機,序列自動機)