【LOJ】#2123. 「HEOI2015」最短不公共子串

题解

我们对于B串建出后缀自动机和序列自动机
对于问题1,枚举左端点然后跑后缀自动机,直到不能匹配作为这个左端点的答案
对于问题2,枚举左端点然后跑序列自动机,直到不能匹配

对于问题3,设f[i][j]表示第前i个字符匹配到后缀自动机上第j个点的最少步数,如果下一步走不了则更新答案
对于问题4,设f[i][j]表示前i个字符匹配到序列自动机上第j个点的最少步数,如果下一步走不了则更新答案

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {putchar('-');x = -x;}
    if(x >= 10) {
        out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 1000000007;
char A[2005],B[2005];
int LA,LB;
int f[2005][4005];
struct SuffixAutoMaton{
    struct SAM_node {
        SAM_node *par,*nxt[26];
        int len;
        SAM_node *find_next(char c) {
            if(nxt[c - 'a']) return nxt[c - 'a'];
            else return NULL;
        }
    }pool[4005],*tail = pool,*root,*last;
    SuffixAutoMaton() {
        root = last = tail++;
    }
    void build(int l,int e) {
        SAM_node *nowp = tail++,*p;
        nowp->len = l;
        for(p = last ; p && !p->nxt[e]; p = p->par) {
            p->nxt[e] = nowp;
        }
        if(!p) nowp->par = root;
        else {
            SAM_node *q = p->nxt[e];
            if(q->len == p->len + 1) nowp->par = q;
            else {
                SAM_node *copyq = tail++;
                *copyq = *q;
                copyq->len = p->len + 1;
                q->par = nowp->par = copyq;
                for( ; p && p->nxt[e] == q ; p = p->par) {
                    p->nxt[e] = copyq;
                }
            }
        }
        last = nowp;
    }
    int calc1(int st) {
        SAM_node *p = root;
        int res = 0;
        for(int i = st ; i <= LA ; ++i) {
            p = p->find_next(A[i]);
            if(!p) break;
            ++res;
        }
        if(res == LA - st + 1) return LA + 1;
        return res + 1;
    }
    int calc3() {
        int m = tail - pool;
        for(int i = 0 ; i <= LA ; ++i) {
            for(int j = 1 ; j <= m ; ++j) {
                f[i][j] = 0x7fffffff;
            }
        }
        f[0][1] = 0;
        int res = LA + 1;
        for(int i = 1 ; i <= LA ; ++i) {
            for(int j = 1 ; j <= m ; ++j) {
                if(f[i - 1][j] != 0x7fffffff) {
                    f[i][j] = min(f[i - 1][j],f[i][j]);
                    SAM_node *p = pool[j - 1].find_next(A[i]);
                    if(!p) res = min(res,f[i - 1][j] + 1);
                    else f[i][p - pool + 1]  = min(f[i][p - pool + 1],f[i][j] + 1);
                }
            }
        }
        return res;
    }
}SAM;
struct LineAutoMaton {
    int ch[2005][26],head[30],next[2005],tot,rt;
    LineAutoMaton() {
        rt = tot = 1;
        for(int i = 0 ; i < 26 ; ++i) head[i] = 1;
    }
    void build(char c) {
        ++tot;next[tot] = head[c - 'a'];
        for(int i = 0 ; i < 26 ; ++i) {
            for(int j = head[i] ; j ; j = next[j]) {
                if(!ch[j][c - 'a']) ch[j][c - 'a'] = tot;
                else break;
            }
        }
        head[c - 'a'] = tot;
    }
    int calc2(int st) {
        int p = rt,L = 0;
        for(int i = st ; i <= LA ; ++i) {
            if(ch[p][A[i] - 'a']) {
                p = ch[p][A[i] - 'a'];
                ++L;
            }
            else break;
        }
        if(L == LA - st + 1) return LA + 1;
        return L + 1;
    }
    int calc4() {
        for(int i = 0 ;i <= LA ; ++i) {
            for(int j = 1 ; j <= tot ; ++j) {
                f[i][j] = 0x7fffffff;
            }
        }
        f[0][1] = 0;
        int res = LA + 1;
        for(int i = 1 ; i <= LA ; ++i) {
            for(int j = 1 ; j <= tot ; ++j) {
                if(f[i - 1][j] != 0x7fffffff) {
                    f[i][j] = min(f[i - 1][j],f[i][j]);
                    int p = ch[j][A[i] - 'a'];
                    if(!p) res = min(res,f[i - 1][j] + 1);
                    else f[i][p] = min(f[i - 1][j] + 1,f[i][p]); 
                }
            }
        }
        return res;
    }   
}LAM;
void Init() {
    scanf("%s",A + 1);
    scanf("%s",B + 1);
    LA = strlen(A + 1);LB = strlen(B + 1);
    for(int i = 1 ; i <= LB ; ++i) {
        SAM.build(i,B[i] - 'a');
        LAM.build(B[i]);
    }
}
void Solve1() {
    int ans = LA + 1;
    for(int i = 1 ; i <= LA ; ++i) {
        ans = min(ans,SAM.calc1(i));
    }
    if(ans > LA) puts("-1");
    else {out(ans),enter;}
}
void Solve2() {
    int ans = LA + 1;
    for(int i = 1 ; i <= LA ; ++i) {
        ans = min(ans,LAM.calc2(i));
    }
    if(ans > LA) puts("-1");
    else out(ans),enter;
}
void Solve3() {
    int ans = SAM.calc3();
    if(ans > LA) puts("-1");
    else out(ans),enter;
}
void Solve4() {
    int ans = LAM.calc4();
    if(ans > LA) puts("-1");
    else out(ans),enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve1();
    Solve2();
    Solve3();
    Solve4();
}

猜你喜欢

转载自www.cnblogs.com/ivorysi/p/9188942.html
今日推荐