zoukankan      html  css  js  c++  java
  • [bzoj4516][Sdoi2016]生成魔咒——后缀自动机

    Brief Description

    魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。
    一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。
    例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生成魔咒有 [1]、
    [1,1]、[1,1,1] 三种。最初 S 为空串。共进行 n 次操作,每次操作是在 S 的结尾加入一个魔咒字符。每次操作后都
    需要求出,当前的魔咒串 S 共有多少种生成魔咒。

    Algorithm Design

    后缀自动机。每次加入一个新的节点的时候统计。

    Code

    #include <cstdio>
    #include <map>
    const int maxn = 100010;
    int n, m, tot = 1, last = 1;
    #define ll long long
    ll ans;
    int len[maxn << 1], fa[maxn << 1];
    std::map<int, int> ch[maxn << 1];
    int calc(int x) { return len[x] - len[fa[x]]; }
    void insert(int x) {
      int p = last, np = last = ++tot;
      len[np] = len[p] + 1;
      while (p && !ch[p][x])
        ch[p][x] = np, p = fa[p];
      if (!p)
        fa[np] = 1, ans += calc(np);
      else {
        int q = ch[p][x];
        if (len[p] + 1 == len[q])
          fa[np] = q, ans += calc(np);
        else {
          int nq = ++tot;
          len[nq] = len[p] + 1;
          ch[nq] = ch[q];
          fa[nq] = fa[q];
          ans += calc(nq) - calc(q);
          fa[q] = fa[np] = nq;
          ans += calc(np) + calc(q);
          while (p && ch[p][x] == q)
            ch[p][x] = nq, p = fa[p];
        }
      }
    }
    int main() {
      scanf("%d", &n);
      for (int i = 1; i <= n; i++) {
        int x;
        scanf("%d", &x);
        insert(x);
        printf("%lld
    ", ans);
      }
    }
    
  • 相关阅读:
    Codesys——限定符的使用方法[来自Codesys的Help]
    分页后台
    多条件查询判断
    添加跟反射
    试图页面分页首选
    动态游标存储过程 表名为参数
    索引器
    泛型 Generics
    Win10 锁屏图片 路径
    SQL2014 error 40 ( Microsoft SQL Server, 错误2)
  • 原文地址:https://www.cnblogs.com/gengchen/p/6550915.html
Copyright © 2011-2022 走看看