CF1276F Asterisk Substrings

抄一下 \(\color{\black}{n}\color{\red}{antf}\) 的题解

我 nantf 怎么这么强啊…这题我不到半个小时就写掉了…为什么div1的时候只有一个人做掉这个 F 啊…这个不是我 nantf 随随便便就写掉的么…

这个 CF 评分 3300 的题为什么这么水啊,直接1A了(

我们先考虑不带 star 的,人人会做,\(\sum len_i - len_{fa_i}\)。

考虑 star 在最前面和最后面,最后一个字符插入到 SAM 之前统计一下 \(\sum len_i - len_{fa_i}\)。

然后考虑一下空字符和 star 字符,略。

考虑其他部分的答案,应该是以 \(i\) 为后缀的数量 \(\times\) \(i+2\) 为前缀的数量,这个挺好做的,下面讲一下。

我们在 \(i\) 对应的 \(sam\) 节点上插入 \(i+2\) 对应 \(rsam\) 的节点。

然后我们知道 \(fa_i\) 所对应的字符串是 \(i\) 的后缀,然后在 \(sam\) 上启发式合并,\(rsam\) 上面求个链并计算贡献,这题就没了。

对于我 nantf 来说代码不是特别好写么…所以丢这里好了


int n;
const int maxn = 4e5 + 54;
char s[maxn];
vector<int> g[maxn];
set<int> Real[maxn];
int Realsize[maxn], rt[maxn], rev[maxn];

int val[maxn], lg[maxn], dep[maxn];

int getmin(int x, int y) { return dep[x] < dep[y] ? x : y; }

int getpw(int x) { return 1 << x; }

struct mt {
  vector<int> g[maxn];
  int st[maxn][22], idx = 0;
  int dfn[maxn], rev[maxn];
  void dfs(int u) {
    st[dfn[u] = ++idx][0] = u;
    rev[dfn[u]] = u;
    for (int v : g[u]) {
      dfs(v);
      st[++idx][0] = u;
    }
  }

  int getlca(int x, int y) {
    if (dfn[x] > dfn[y]) x ^= y ^= x ^= y;
    x = dfn[x], y = dfn[y];
    int t = lg[y - x + 1];
    return getmin(st[x][t], st[y - getpw(t) + 1][t]);
  }
} qwq;

int getdis(int x, int y) {
  const int lca = qwq.getlca(x, y);
  return dep[x] + dep[y] - 2 * dep[lca];
}

int ans = 0;

void insert(int v, int u) {
  for (int t : Real[v]) {
    if (Real[u].count(t)) {
      continue;
    } else {
      auto it = Real[u].insert(t).fir;
      auto l = it;
      auto r = it;
      if (l == Real[u].begin())
        l = --Real[u].end();
      else
        --l;
      ++r;
      if (r == Real[u].end()) r = Real[u].begin();
      int a = qwq.rev[*l];
      int b = qwq.rev[*r];
      Realsize[u] += getdis(a, qwq.rev[t]) + getdis(b, qwq.rev[t]) - getdis(a, b);
    }
  }
  Real[v].clear();
  Realsize[v] = 0;
}

void dfs(int u) {
  for (int v : g[u]) {
    dfs(v);
    if (sz(Real[rt[u]]) < sz(Real[rt[v]])) swap(rt[u], rt[v]);
    insert(rt[v], rt[u]);
  }
  ans += (Realsize[rt[u]] >> 1) * val[u];
}

struct suffixautomaton {
  int ch[maxn][26];
  int cnt, las;

  suffixautomaton() { cnt = las = 1; }

  int len[maxn], fa[maxn];
  void ins(int c) {
    int p = las, np = las = ++cnt;
    len[np] = len[p] + 1;
    for (; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
    if (!p) {
      fa[np] = 1;
    } else {
      int q = ch[p][c];
      if (len[q] == len[p] + 1) {
        fa[np] = q;
      } else {
        int nq = ++cnt;
        len[nq] = len[p] + 1;
        memcpy(ch[nq], ch[q], sizeof(ch[q]));
        fa[nq] = fa[q];
        fa[q] = fa[np] = nq;
        for (; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
      }
    }
  }

  void build1() {
    rep(i, 2, cnt) g[fa[i]].pb(i);
    rep(i, 1, cnt) rt[i] = i;
    rep(i, 2, cnt) val[i] = len[i] - len[fa[i]];
    int p = 1;
    rep(i, 1, n - 2) {
      int c = s[i] - ‘a‘;
      p = ch[p][c];
      Real[p].insert(qwq.dfn[rev[i + 2]]);
      Real[p].insert(qwq.dfn[1]);
      Realsize[p] = dep[rev[i + 2]] * 2;
    }
    dfs(1);
  }

  void build2() {
    rep(i, 2, cnt) { dep[i] = len[i], qwq.g[fa[i]].pb(i); }
    qwq.dfs(1);
    lg[1] = 0;
    rep(i, 2, maxn - 1) { lg[i] = lg[i >> 1] + 1; }
    rep(j, 1, 20) {
      rep(i, 1, qwq.idx - getpw(j) + 1) qwq.st[i][j] =
          getmin(qwq.st[i][j - 1], qwq.st[i + getpw(j - 1)][j - 1]);
    }
  }

  int getcnt() {
    int ans = 0;
    rep(i, 2, cnt) ans += len[i] - len[fa[i]];
    return ans;
  }
} sam, rsam;

signed main() {
  // code begin.
  in >> (s + 1), n = strlen(s + 1);
  rep(i, 1, n) {
    if (i == n) ans += sam.getcnt();
    sam.ins(s[i] - ‘a‘);
  }
  Rep(i, n, 1) {
    if (i == 1) ans += rsam.getcnt();
    rsam.ins(s[i] - ‘a‘);
    rev[i] = rsam.las;
  }
  ans += sam.getcnt();
  rsam.build2();
  sam.build1();
  ++ans, ++ans;
  out << ans << ‘\n‘;
  return 0;
  // code end.
}

原文地址:https://www.cnblogs.com/Isaunoya/p/12654769.html

时间: 2024-10-15 03:23:11

CF1276F Asterisk Substrings的相关文章

@codeforces - [email&#160;protected] Asterisk Substrings

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个包含 n 个小写字母的字符串 s,用 s 生成 n 个串 t1...n,其中 ti 等于字符串 s 将第 i 个字符替换为 * 得到的字符串. 特别注意:这里的 * 只是一个字符,并不具有其他含义(如通配符). 求有多少字符串,在 {s, t1, t2, ..., tn} 中作

[Leetcode] DP-- 467. Unique Substrings in Wraparound String

Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz", so s will look like this: "...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....". Now we have another string p. Your job is to find

uva 10829 - L-Gap Substrings(后缀数组)

题目链接:uva 10829 - L-Gap Substrings 题目大意:给定一个字符串,问有多少字符串满足UVU的形式,要求U非空,V的长度为g. 解题思路:对字符串的正序和逆序构建后缀数组,然后枚举U的长度l,每次以长度l分区间,在l和l+d+g所在的两个区间上确定U的最大长度. #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using nam

[LeetCode] Unique Substrings in Wraparound String 封装字符串中的独特子字符串

Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz", so s will look like this: "...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....". Now we have another string p. Your job is to find

POJ 3415 Common Substrings (求长度不小于k的公共子串的个数)

Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10002   Accepted: 3302 Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|. Given two strings A, B and one integer K, we define S,

字符串(后缀数组):POJ 3415 Common Substrings

Common Substrings Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|. Given two strings A, B and one integer K, we define S, a set of triples (i, j, k): S = {(i, j, k) | k≥K, A(i, k)=B(j, k)}. You are to give

SPOJ 题目694 Distinct Substrings(后缀数组,求不同的子串个数)

DISUBSTR - Distinct Substrings no tags Given a string, we need to find the total number of its distinct substrings. Input T- number of test cases. T<=20; Each test case consists of one string, whose length is <= 1000 Output For each test case output

Asterisk[1]

Asterisk[1]是一款GPLv2协议下的开源电话应用平台.简单来说,Asterisk是一个服务器应用,能够完成发起电话呼叫.接受电话呼叫.对电话呼叫进行定制处理. 1.2.1 通道驱动 asterisk的通道驱动接口是最复杂也是最重要的可用接口.asteisk的通道API提供了对各种通信协议的抽象,使得asterisk的各种功能特性不必关心具体的通信协议.该组件主要是负责在asterisk通道抽象和具体的通信协议实现中的通信. asterisk通道驱动接口的定义是ast_channel_t

解题报告 之 POJ1226 Substrings

解题报告 之 POJ1226 Substrings Description You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings. Input The first li