bzoj4032[HEOI2015]最短不公共子串

http://www.lydsy.com/JudgeOnline/problem.php?id=4032

后缀自动机+序列自动机

序列自动机这东西好像很高端的样子。。。。。。

其实很简单的啦。。。。。。

详细可以看一下我的博客序列自动机

对字符串A构建后缀自动机$str_A$和序列自动机$seq_A$;类似地,对字符串B也构建后缀自动机$str_B$和序列自动机$seq_B$。

然后对于4个询问我们分别拿出1个自动机,如第一个询问拿出$str_A$和$str_B$(下面以第一个询问为例):

记$vis[x][y]$表示在$str_A$中到编号为$x$的点且在$str_B$中到编号为$y$的点的最短长度是多少,这个可以$BFS$。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b)  for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxN=2000;

struct string_automation
  {
      struct Tnode
        {
            int ch[26],fail,len;
            inline Tnode(){mmst(ch,0);fail=len=0;}
        }a[2*maxN+100];int MID;
      int root,end;
      inline int newnode(){a[++MID]=Tnode();return MID;}
      inline void clear(){MID=0;root=end=newnode();}
      inline void add(int x)
        {
            int last=newnode(),p;
            a[last].len=a[end].len+1;
            for(p=end;p && !a[p].ch[x];p=a[p].fail)a[p].ch[x]=last;
            if(!p) a[last].fail=root;
            else
              {
                  int q=a[p].ch[x];
                  if(a[p].len+1==a[q].len) a[last].fail=q;
                  else
                    {
                        int nq=newnode(),tmp;
                        a[nq]=a[q];
                        a[q].fail=a[last].fail=nq;
                        a[nq].len=a[p].len+1;
                        for(tmp=p;tmp && a[tmp].ch[x]==q;tmp=a[tmp].fail)a[tmp].ch[x]=nq;
                    }
              }
            end=last;
        }
      inline void insert(char *s)
        {
            int i,len=strlen(s+1);
            clear();
            re(i,1,len)add(s[i]-'a');
        }
  };

struct sequence_automation
  {
      struct Tnode
        {
            int ch[27],fail;
            inline Tnode(){mmst(ch,0);fail=0;}
        }a[maxN+100];int MID;
      int last[27];
      inline int newnode(){a[++MID]=Tnode();return MID;}
      inline void clear(){MID=0;mmst(last,0);last[26]=newnode();}
      inline void add(int x)
        {
            int i,o=newnode();
            re(i,0,26)
              for(int p=last[i];p && !a[p].ch[x];p=a[p].fail)a[p].ch[x]=o;
            a[o].fail=last[x],last[x]=o;
        }
      inline void insert(char *s)
        {
            int i,len=strlen(s+1);
            clear();
            re(i,1,len)add(s[i]-'a');
        }
  };

char A[maxN+100],B[maxN+100];
string_automation str_A,str_B;
sequence_automation seq_A,seq_B;

int vis[2*maxN+100][2*maxN+100];
queue<PII>Q;
template<class T1,class T2>inline int BFS(T1 &A,T2 &B)
  {
      mmst(vis,0);
      while(!Q.empty())Q.pop();
      vis[1][1]=0;
      Q.push(PII(1,1));
      while(!Q.empty())
        {
            int i,x=Q.front().fi,y=Q.front().se;Q.pop();
            re(i,0,25)
              {
                  if(!A.a[x].ch[i])continue;
                  if(!B.a[y].ch[i])return vis[x][y]+1;
                  int tx=A.a[x].ch[i],ty=B.a[y].ch[i];
                  if(vis[tx][ty])continue;
                  vis[tx][ty]=vis[x][y]+1;
                  Q.push(PII(tx,ty));
              }
        }
      return -1;
  }

int main()
  {
      freopen("bzoj4032.in","r",stdin);
      freopen("bzoj4032.out","w",stdout);
      SF("%s\n",A+1);str_A.insert(A);seq_A.insert(A);
      SF("%s\n",B+1);str_B.insert(B);seq_B.insert(B);
      cout<<BFS(str_A,str_B)<<endl;
      cout<<BFS(str_A,seq_B)<<endl;
      cout<<BFS(seq_A,str_B)<<endl;
      cout<<BFS(seq_A,seq_B)<<endl;
      return 0;
  }
View Code

 

posted @ 2015-09-03 23:01  maijing  阅读(448)  评论(0编辑  收藏  举报