zoukankan      html  css  js  c++  java
  • [HEOI2015]最短不公共子串

    [HEOI2015]最短不公共子串

    题面

    在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。

    下面给出一些定义:

    • 一个串的“子串”指的是它的连续的一段,例如 bcd 是 abcdef 的子串,但 bde 不是。
    • 一个串的“子序列”指的是它的可以不连续的一段,例如 bde 是 abcdef 的子串,但 bdd 不是。

    下面,给两个小写字母串 a, ba,b,请你计算:

    1. a 的一个最短的子串,它不是 b 的子串。
    2. a 的一个最短的子串,它不是 b 的子序列。
    3. a 的一个最短的子序列,它不是 b 的子串。
    4. a 的一个最短的子序列,它不是 b 的子序列。

    题解

    原本1, 用自动机match写的, 当匹配失败的时候取最小值, 然而 a = aabba, b = aabbd, 答案是2, 而不是5

    所以要bfs写, 转移就完事了, 再SAM, SQAM上转移就行, 注意自动机空间是 2n

    代码

    struct SAM { //不管是不是多组数据都调用init
        static const int N = 2e3 + 5, M = 26, C = 'a';
        struct node { int fa, len, ne[M]; } tr[N << 1];
        int sz, las, len, c[N], rk[N << 1], cnt[N << 1];
        int sum[N << 1]; //排名为i的节点为头包含的字串数量
        void init() {
            rep (i, 1, sz)
                tr[i].len = tr[i].fa = c[i] = 0, memset(tr[i].ne, 0, sizeof tr[i].ne);
            sz = las = 1;
        }
        void add(int ch) {
            int p = las, cur = las = ++sz;
            tr[cur].len = tr[p].len + 1; ++cnt[cur];
            for (; p && !tr[p].ne[ch]; p = tr[p].fa) tr[p].ne[ch] = cur;
            if (p == 0) { tr[cur].fa = 1; return; }
            int q = tr[p].ne[ch];
            if (tr[q].len == tr[p].len + 1) { tr[cur].fa = q; return; }
            int nq = ++sz; tr[nq] = tr[q]; tr[nq].len = tr[p].len + 1;
            for (; p && tr[p].ne[ch] == q; p = tr[p].fa) tr[p].ne[ch] = nq;
            tr[q].fa = tr[cur].fa = nq;
        }
        void build(char *s) {
            for (int& i = len; s[i]; ++i) add(s[i] - C);
        }
    } sama, samb;
    
    struct SqAM {
        static const int N = 2e3 + 5, M = 26, C = 'a';
        struct Node { int fa, ne[26]; } tr[N << 1]; 
        int rt, tot, lst[M];
        int newNode() { return ++tot, memset(tr[tot].ne, 0, sizeof tr[0].ne), tot; }
        void init() { tot = 0; rep (i, 0, M - 1) lst[i] = 1; rt = newNode(); }
        void insert(int ch) {
            int p = lst[ch], cur = newNode(); tr[cur].fa = p;
            rep (i, 0, M - 1) for (int j = lst[i]; j && !tr[j].ne[ch]; j = tr[j].fa)
                tr[j].ne[ch] = cur;
            lst[ch] = cur;
        }
        void build(char* s) { for (int i = 0; s[i]; insert(s[i++] - C)); }
    } A, B;
    
    const int N = 2e3 + 5;
    int st[N << 1][N << 1];
    char a[N], b[N];
    
    int bfs1() {
        queue<pair<PII, int>> q; q.push({ { 1, 1, }, 0 }); st[1][1] = 1;
        while (!q.empty()) {
            auto cur = q.front(); q.pop();
            int x = cur.fi.fi, y = cur.fi.se, t = cur.se;
            rep (i, 0, 25) {
                int nx = sama.tr[x].ne[i], ny = samb.tr[y].ne[i];
                if (nx && ny) if (st[nx][ny] != 1) st[nx][ny] = 1, q.push({ { nx, ny }, t + 1 });
                if (nx && !ny) return t + 1;
            }
        }
        return -1;
    }
    
    int bfs2() {
        queue<pair<PII, int>> q; q.push({ { 1, 1, }, 0 }); st[1][1] = 1;
        while (!q.empty()) {
            auto cur = q.front(); q.pop();
            int x = cur.fi.fi, y = cur.fi.se, t = cur.se;
            rep (i, 0, 25) {
                int nx = sama.tr[x].ne[i], ny = B.tr[y].ne[i];
                if (nx && ny) if (st[nx][ny] != 1) st[nx][ny] = 1, q.push({ { nx, ny }, t + 1 });
                if (nx && !ny) return t + 1;
            }
        }
        return -1;
    }
    
    int bfs3() {
        queue<pair<PII, int>> q; q.push({ { 1, 1, }, 0 }); st[1][1] = 3;
        while (!q.empty()) {
            auto cur = q.front(); q.pop();
            int x = cur.fi.fi, y = cur.fi.se, t = cur.se;
            rep (i, 0, 25) {
                int nx = A.tr[x].ne[i], ny = samb.tr[y].ne[i];
                if (nx && ny) if (st[nx][ny] != 3) st[nx][ny] = 3, q.push({ { nx, ny }, t + 1 });
                if (nx && !ny) return t + 1;
            }
        }
        return -1;
    }
    
    int bfs4() {
        queue<pair<PII, int>> q; q.push({ { 1, 1, }, 0 }); st[1][1] = 4;
        while (!q.empty()) {
            auto cur = q.front(); q.pop();
            int x = cur.fi.fi, y = cur.fi.se, t = cur.se;
            rep (i, 0, 25) {
                int nx = A.tr[x].ne[i], ny = B.tr[y].ne[i];
                if (nx && ny) if (st[nx][ny] != 4) st[nx][ny] = 4, q.push({ { nx, ny }, t + 1 });
                if (nx && !ny) return t + 1;
            }
        }
        return -1;
    }
    
    int main() {
        cin >> a >> b; samb.init(); samb.build(b); B.init(); B.build(b);
        sama.init(); sama.build(a); A.init(); A.build(a);
        cout << bfs1() << '
    ' << bfs2() << '
    ' << bfs3() << '
    ' << bfs4();
        return 0;
    }
    
  • 相关阅读:
    从小白到全栈的前端学习路径
    Vue初学者可能不知道的坑
    vue的基础使用
    15-浮动
    02-css的选择器
    深入理解JavaScript的闭包
    深入理解JavaScript的闭包,前戏— 作用域和词法作用域
    JavaScript简介
    02-HTML5新的input属性
    springboot+spring session+redis+nginx实现session共享和负载均衡
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/14141853.html
Copyright © 2011-2022 走看看