【[HEOI2015]最短不公共子串】后缀自动机+序列自动机

1218 1218  

4032: [HEOI2015]最短不公共子串

Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 815  Solved: 416 [Submit][Status][Discuss]

Description

 在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。
一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
下面,给两个小写字母串A,B,请你计算:
(1) A的一个最短的子串,它不是B的子串
(2) A的一个最短的子串,它不是B的子序列
(3) A的一个最短的子序列,它不是B的子串
(4) A的一个最短的子序列,它不是B的子序列

Input

有两行,每行一个小写字母组成的字符串,分别代表A和B。

Output

输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.

Sample Input

aabbcc abcabc

Sample Output

2 4 2 4

HINT

 对于100%的数据,A和B的长度都不超过2000 我们考虑构建后缀自动机和序列自动机(类同后缀自动机,只是序列自动机是处理子序列问题,后缀自动机处理子串问题,会后缀自动机的话看代码就很好理解),然后放在两两自动机之间跑一个bfs就可以了。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 2005;
char a[maxn],b[maxn];

struct hzzdh{
    int son[maxn*2][26],par[maxn*2],mx[maxn*2],tot,las;
    void init() { las=tot=1; }
    void extend(int c) {
        int p=las,np=++tot;mx[np]=mx[p]+1;
        for(;p&&(!son[p][c]);p=par[p]) son[p][c]=np;
        las = np;
        if(!p) { par[np]=1; return; }
        int q = son[p][c];
        if(mx[p]+1==mx[q]) { par[np]=q; return; }
        int nq = ++tot; memcpy(son[nq],son[q],sizeof son[q]);
        mx[nq] = mx[p]+1; par[nq]=par[q]; par[q] = par[np] = nq;
        for(;p&&son[p][c]==q;p=par[p]) son[p][c]=nq;
    }
    void insert(char *s) {
        int len = strlen(s+1);
        for(int i=1;i<=len;i++) extend(s[i]-'a');
    }   
}sam[2];

struct xlzdj{
    int son[maxn][26],la[26],par[maxn],tot;
    void init() { tot=1; for(int i=0;i<26;i++)la[i]=1;}
    void extend(int c) {
        int np = ++tot; par[np] = la[c];
        for(int j=0;j<26;j++)
        for(int p=la[j];p&&(!son[p][c]);p=par[p]) son[p][c]=np;
        la[c]=np;
    }
    void insert(char *s) {
        int len = strlen(s+1);
        for(int i=1;i<=len;i++) extend(s[i]-'a');
    }
}sqm[2];
struct node{int o1,o2,d;};
queue<node>q;
bool vis[maxn<<1][maxn<<1];
void solve(int a[][26],int b[][26]) {
    while(q.size())q.pop();
    memset(vis,0,sizeof vis); vis[1][1]=1;
    q.push((node){1,1,0});
    while(q.size()) {
        node u = q.front(); q.pop();
        for(int c=0;c<26;c++) {
            node v = (node){a[u.o1][c],b[u.o2][c],u.d+1};
            if(vis[v.o1][v.o2]||(!v.o1)) continue;
            if(!v.o2) { printf("%d\n",v.d); return; }
            q.push(v); vis[v.o1][v.o2]=1;
        }
    }
    puts("-1");
}
int main() {
    scanf("%s%s",&a[1],&b[1]);
    sqm[0].init();sqm[1].init();sam[0].init();sam[1].init();
    sqm[0].insert(a); sqm[1].insert(b); sam[0].insert(a); sam[1].insert(b);
    solve(sam[0].son,sam[1].son);
    solve(sam[0].son,sqm[1].son);
    solve(sqm[0].son,sam[1].son);
    solve(sqm[0].son,sqm[1].son);
}
 
posted @ 2018-12-18 18:46  Newuser233  阅读(10)  评论(0)    收藏  举报