• BZOJ4032 [HEOI2015]最短不公共子串


    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即可;否则,可以乱搞出什么“子序列自动机”(只需要把每个节点连到它的下一个a、下一个b、...下一个z即可),然后bfs。

    (为了一句last=ne调了一个小时QAQ)

    附代码:

    #include <algorithm>
    #include <bitset>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    const int N = 4050;
    struct Node{
      int nxt[26], pa, len;
    };
    struct Automation{
      Node nodes[N];
      int cnt;
      inline int newNode(int l = 0) {
        memcpy(&nodes[cnt].nxt, &nodes[l].nxt, sizeof(int) * 26);
        nodes[cnt].pa = nodes[l].pa;
        nodes[cnt].len = nodes[l].len;
        return cnt++;
      }
      int root;
      int seq_last[26], last;
      void init() {
        memset(&nodes[0], 0, sizeof(Node));
        cnt = 1;
        root = newNode();
        for (int i = 0; i < 26; ++i)
          seq_last[i] = root;
        last = root;
      }
      void seq_append(int x) {
        int ne = newNode();
        for (int i = 0; i < 26; ++i)
          for (int q = seq_last[i]; q && !nodes[q].nxt[x]; q = nodes[q].pa)
            nodes[q].nxt[x] = ne;
        nodes[ne].pa = seq_last[x];
        seq_last[x] = ne;
      }
      void suffix_append(int x) {
        int ne = newNode();
        nodes[ne].len = nodes[last].len + 1;
        int q = last;
        while (q && !nodes[q].nxt[x]) {
          nodes[q].nxt[x] = ne;
          q = nodes[q].pa;
        }
        if (!q) {
          nodes[last = ne].pa = root;
          return;
        }
        int p = nodes[q].nxt[x];
        if (nodes[p].len == nodes[q].len + 1) {
          nodes[last = ne].pa = p;
          return;
        }
        int pq = newNode(p);
        nodes[pq].len = nodes[q].len + 1;
        nodes[last = ne].pa = nodes[p].pa = pq;
        while (q && nodes[q].nxt[x] == p) {
          nodes[q].nxt[x] = pq;
          q = nodes[q].pa;
        }
      }
    };
    struct AAA{
      int x, y, len;
      AAA(int a, int b, int c) : x(a), y(b), len(c) {}
    };
    std::bitset<N> vis[N];
    std::queue<AAA> Q;
    int bfs(const Automation &A, const Automation &B) {
      while (!Q.empty()) Q.pop();
      Q.push(AAA(A.root, B.root, 0));
      for (int i = 0; i < A.cnt; ++i)
        vis[i].reset();
      vis[A.root][B.root] = 1;
      while (!Q.empty()) {
        AAA x = Q.front(); Q.pop();
        const Node &a = A.nodes[x.x], &b = B.nodes[x.y];
        for (int i = 0; i < 26; ++i) {
          int l = a.nxt[i], r = b.nxt[i];
          if (!l) continue;
          if (!r) return x.len + 1;
          if (!vis[l][r]) Q.push(AAA(l, r, x.len + 1));
          vis[l][r] = 1;
        }
      }
      return -1;
    }
    Automation a, b;
    char s[N], p[N];
    int main() {
      scanf("%s%s", s, p);
      a.init();
      for (char *r = s; *r; ++r)
        a.suffix_append(*r - 'a');
      b.init();
      for (char *r = p; *r; ++r)
        b.suffix_append(*r - 'a');
      printf("%d
    ", bfs(a, b));
      b.init();
      for (char *r = p; *r; ++r)
        b.seq_append(*r - 'a');
      printf("%d
    ", bfs(a, b));
      a.init();
      for (char *r = s; *r; ++r)
        a.seq_append(*r - 'a');
      int ans4 = bfs(a, b);
      b.init();
      for (char *r = p; *r; ++r)
        b.suffix_append(*r - 'a');
      printf("%d
    ", bfs(a, b));
      printf("%d
    ", ans4);
      return 0;
    }
    

      

  • 相关阅读:
    桌面图标背景透明
    如何做好一个中小型企业计算机网络管理员
    打开IE8总是提示欢迎使用?怎样使它不提示?
    js 操作select和option,添加select列
    bios 被加密,怎么进入bios
    Foxmail自动收取新邮件
    代码片段
    提高生活幸福感的13个方法
    水晶报表的真实体验
    游标替代
  • 原文地址:https://www.cnblogs.com/y-clever/p/7373033.html
Copyright © 2020-2023  润新知