1 条题解

  • 0
    @ 2026-5-5 20:14:53

    根据你的要求,我已将上一份题解中所有数字和数学公式(包括变量、表达式、运算符号等)严格用单个 $ 包裹。修改后的题解如下:


    D. “a” 字符串问题 详细题解

    题目重述

    给定一个由小写字母组成的字符串 ss,统计所有非空字符串 t"a"t \neq \text{"a"} 的个数,满足可以将 ss 划分成若干子串,每个子串要么等于 tt,要么等于单个字符 "a"\text{"a"},且至少有一个子串等于 tt

    划分指将 ss 表示为 t1+t2++tk=st_1 + t_2 + \dots + t_k = s(拼接)。

    核心观察

    ss 中所有非 ’a’\text{'a'} 字符的位置为 p0,p1,,pm1p_0, p_1, \dots, p_{m-1}mm 为非 ’a’\text{'a'} 的个数)。由于划分中只允许出现 tt 或单个 ’a’\text{'a'},任何非 ’a’\text{'a'} 字符只能被 tt 段覆盖。tt 段可以重复出现,也可能只出现一次。因此我们将符合条件的 tt 分为两大类:

    1. 周期重复型ttss 中作为“基本块”多次出现,覆盖所有非 ’a’\text{'a'} 字符,其余部分均为单个 ’a’\text{'a'}。这要求所有非 ’a’\text{'a'} 字符的位置相对第一个非 ’a’\text{'a'} 字符的位置之差具有周期性,且 tt 的内容由这些位置决定。
    2. 单一 tt 段型tt 只出现一次,其余部分全是 ’a’\text{'a'}。此时 tt 必须是一个包含所有非 ’a’\text{'a'} 字符的连续子串。

    两类解可能有重叠,需要容斥。

    符号定义

    • n=sn = |s|
    • ’a’\text{'a'} 位置:p0<p1<<pm1p_0 < p_1 < \dots < p_{m-1}
    • L=p0L = p_0R=pm1R = p_{m-1}

    情况一:全为 ’a’\text{'a'}

    m=0m = 0,则 ss 仅由 ’a’\text{'a'} 组成。任何 t"a"t \neq \text{"a"} 必须全部由 ’a’\text{'a'} 构成(因为划分中只能出现 ’a’\text{'a'}tt)。因此 tt 可以是长度 22nn 的任意全 ’a’\text{'a'} 串,共 n1n-1 个。

    情况二:只有一个非 ’a’\text{'a'} 字符

    此时 m=1m = 1L=RL = Rtt 必须包含这个唯一的非 ’a’\text{'a'} 字符,且 tt 可以是任意一个包含该字符的连续子串(长度至少 11)。由于 tt 不能等于 ’a’\text{'a'},所以如果该非 ’a’\text{'a'} 字符本身不是 ’a’\text{'a'},则长度为 11tt 就是它本身,合法。因此所有可能的 tt 为:左端点可以从 00LL,右端点可以从 LLn1n-1,且左端点 \le 右端点。这样的子串共有 (L+1)(nL)(L+1) \cdot (n-L) 个。

    情况三:多个非 ’a’\text{'a'} 字符(m2m \ge 2

    3.1 周期重复型 tt

    假设存在一个 tt 重复出现多次(可能夹杂单个 ’a’\text{'a'})。设 tt 的长度为 lenlen。那么所有非 ’a’\text{'a'} 字符的位置必须满足:存在一个参考起点 startstarttt 段的起始位置),使得每个 pip_istartstart 的差是 lenlen 的整数倍,且 s[pi]s[p_i] 等于 tt 中对应的字符。由于 p0p_0 是第一个非 ’a’\text{'a'} 字符,它必然落在第一个 tt 段内。我们可以将 startstart 取为 p0p_0 或者更左的位置?实际上,因为 tt 段可以前面有若干个 ’a’\text{'a'} 字符,p0p_0 不一定正好是 tt 的起始。记 tt 段的起始下标为 xx,则 xp0x \le p_0,且 p0x=dp_0 - x = d0d<len0 \le d < len)。那么所有非 ’a’\text{'a'} 字符的位置满足 pid(modlen)p_i \equiv d \pmod{len},且 s[pi]=t[d]s[p_i] = t[d](其中 tt 的第 dd 个字符为 t[d]t[d])。由于 p0p_0 是第一个,d=p0xd = p_0 - xxx 未知。但是,我们可以通过枚举 dd 来考虑,但复杂度可能较高。

    更简洁的方法:注意到 tt 段在 ss 中必须完整出现,且所有非 ’a’\text{'a'} 字符的相对模式由 tt 决定。另一种常见思路是:如果忽略开头的 ’a’\text{'a'} 前缀,直接令 t=s[L..L+len1]t = s[L..L+len-1] 作为候选。然而 tt 的起点也可能在 LL 的左边(例如 s="abab"s=\text{"abab"} 中,t="ab"t=\text{"ab"} 从位置 00 开始,而 L=1L=1)。直接枚举所有可能的 lenlen 和偏移量 dd 会超时。

    观察可知,tt 的长度 lenlen 必须整除所有差值 pip0p_i - p_0最大公约数 gg,即 lenglen \mid g。这是因为 pip0p_i - p_0 必须是 lenlen 的倍数(因为 pip_ip0p_0 在同一个 tt 段内或不同段?实际上,若 tt 重复出现,则任意两个非 ’a’\text{'a'} 字符之间的差都是 lenlen 的整数倍,所以 pip0p_i - p_0lenlen 的倍数。因此 lenlen 是这些差值的公约数,从而 lenglen \mid g。因此可能的 lenlen 只能是 gg 的正因子。

    tt 的起始位置不一定是 LL。若 lenglen \mid g,我们可以将 tt 的起始点选为 LL 或更左的位置?考虑到 p0p_0 在第一个 tt 段内的偏移量 dd 可以取 00len1len-1,但 dd 必须使得 s[L]s[L] 等于 t[d]t[d],且 t[d]t[d] 就是 s[L]s[L](因为 p0p_0 对应 tt 的第 dd 个字符)。所以我们实际上需要根据可能的 dd 来构造 tt,但 dd 的唯一作用是决定 ttp0p_0 的相对位置。由于我们关心的是 tt 的字符串内容,而不是它的绝对起始位置,我们可以将 tt 定义为从 LdL-d 开始到 Ld+len1L-d+len-1 的子串。然而,枚举 dd 需要 O(len)O(len),总复杂度可能较大。

    一个更简单的处理是:直接枚举所有可能的 tt 段长度 lenlengg 的因子),并假设 ttLL 为起始,即 t=s[L..L+len1]t = s[L..L+len-1]。然后检查这样定义的 tt 是否能够通过将 ss 划分为 tt’a’\text{'a'} 来覆盖整个字符串。如果通过,则 tt 是一个合法解。这个做法会漏掉那些 tt 起始于 LL 左侧的情况吗?事实上,如果存在一个合法的 tt 起始于 x<Lx < L,那么我们可以将 xxL1L-1 的这段前缀全部由 ’a’\text{'a'} 组成(因为 LL 是第一个非 ’a’\text{'a'} 字符,所以这段前缀全是 ’a’\text{'a'})。因此,将 tt 的起始点向右移动到 LL 并不会破坏划分:只需将前面的 ’a’\text{'a'} 段独立出来,tt 段改为从 LL 开始即可。但这样 tt 的内容会改变(因为从 LL 开始取 lenlen 个字符不等于原来的 tt)。所以不能直接移动。实际上,若 tt 起始于 x<Lx<L,则 tt 的前 LxL-x 个字符全是 ’a’\text{'a'},后面部分才是非 ’a’\text{'a'} 模式。而 tt 不能是 ’a’\text{'a'},所以 tt 中至少有一个非 ’a’\text{'a'} 字符。那么 tt 的右段(从位置 LL 开始)就是 tt 的后缀。是否有可能这个后缀本身也是一个合法 tt?不一定,因为 tt 可能以多个 ’a’\text{'a'} 开头。但我们可以观察到,如果 tt’a’\text{'a'} 开头,那么它前面的那些 ’a’\text{'a'} 也可以单独作为 ’a’\text{'a'} 段,而 tt 实际上可以缩减为去掉这些前导 ’a’\text{'a'} 的版本。因为划分中允许单独的 ’a’\text{'a'},所以 tt 的前导 ’a’\text{'a'} 完全可以分离出去。因此,任何合法 tt 都可以通过去掉前导连续 ’a’\text{'a'} 得到一个不以前导 ’a’\text{'a'} 开头的等价 tt',且 tt' 的第一个字符就是 s[L]s[L](因为 LL 是第一个非 ’a’\text{'a'})。所以 tt' 必定从 LL 开始。因此,我们只需要考虑那些以 LL 为起点的 tt(即 t=s[L..L+len1]t = s[L..L+len-1]),然后再检查合法性。这样不会漏解。同理,tt 也可以有后缀 ’a’\text{'a'},但后缀 ’a’\text{'a'} 可以归入后续的 ’a’\text{'a'} 段,不影响划分。

    因此,我们只枚举长度 lenlengg 的正因子,并且令 t=s[L..L+len1]t = s[L..L+len-1]。然后检查是否能用 tt’a’\text{'a'} 划分 ss:从 i=0i=0 开始扫描,如果 s[i]=’a’s[i] = \text{'a'} 则跳过(作为单独 ’a’\text{'a'} 段);否则尝试匹配 tt,若匹配成功则跳过 lenlen 个字符并记录使用了 tt,否则失败。最后还要保证至少使用了一次 tt。若扫描成功,则 tt 是一个合法解。

    3.2 单一 tt 段型

    tt 只出现一次,其余部分全是 ’a’\text{'a'}。那么 tt 必须是一个包含所有非 ’a’\text{'a'} 字符的连续子串,即左端点 ll 可以取 00LL 的任意值,右端点 rr 可以取 RRn1n-1 的任意值,且 lrl \le r。显然,这样的子串共有 (L+1)(nR)(L+1) \cdot (n-R) 个。注意 tt 本身不能是 ’a’\text{'a'},但由于 tt 包含至少一个非 ’a’\text{'a'} 字符,自动满足。

    3.3 重叠部分(容斥)

    某些 tt 既属于周期重复型,又属于单一 tt 段型。也就是那些长度 lenlen 满足 lenRL+1len \ge R-L+1(因为要包含整个非 ’a’\text{'a'} 区间)且通过周期检查的 tt。这些 tt 在两类中被重复计数,需要减去一次。因此最终答案为:

    $$\text{ans} = \text{period\_cnt} + (L+1)(n-R) - \text{overlap} $$

    其中 period_cnt\text{period\_cnt} 是按上述扫描判定的合格长度个数,overlap\text{overlap} 是其中满足 lenRL+1len \ge R-L+1 的个数。

    边界情况:整个字符串 ss 本身

    ss 本身作为 tt 时,它显然属于周期重复型(len=nlen=n,此时 L=0L=0nn 必须是 gg 的因子才会被枚举到)。如果 L=0L=0nngg 的因子,则 len=nlen=n 会被枚举且通常通过检查(只要 ss 本身满足自己的模式),所以它已被计入 period_cnt\text{period\_cnt}。否则(L>0L>0nn 不是 gg 的因子),ss 本身不会被周期枚举覆盖,但它显然是合法解(单一 tt 段型中 l=0,r=n1l=0,r=n-1 已经包含)。因此无需额外处理。但在实现中,单一 tt 段型已经包含了整个字符串,所以周期解中若包含整个字符串会产生重叠,容斥会处理。

    算法步骤总结

    1. 读入 ssn=sn=|s|
    2. 找出所有非 ’a’\text{'a'} 的位置 pospos。若 pospos 为空,输出 n1n-1
    3. L=pos[0]L = pos[0]R=pos.back()R = pos.back()m=posm = |pos|
    4. m=1m = 1,输出 (L+1)(nL)(L+1)(n-L)
    5. 计算 g=gcdi1(pos[i]pos[0])g = \gcd_{i\ge 1}(pos[i]-pos[0])
    6. 枚举 gg 的所有正因子 lenlen
      • len>nLlen > n-L 则跳过。
      • t=s.substr(L,len)t = s.substr(L, len)
      • 检查所有非 ’a’\text{'a'} 字符是否满足 s[pos[i]]=s[L+((pos[i]L)modlen)]s[pos[i]] = s[L + ((pos[i]-L) \bmod len)]。若不满足,跳过。
      • 扫描整个 ss,模拟划分:从 i=0i=0 开始,若 s[i]=’a’s[i]=\text{'a'}i++i++;否则若 i+lenni+len \le ns.substr(i,len)=ts.substr(i, len) = t,则 i+=leni += len 并标记已使用 tt;否则失败。
      • 若成功且使用了 tt,则 period_cnt++\text{period\_cnt}++,若 lenRL+1len \ge R-L+1overlap++\text{overlap}++
    7. 计算 span_cnt=(L+1)(nR)\text{span\_cnt} = (L+1)(n-R)
    8. 输出 $\text{period\_cnt} + \text{span\_cnt} - \text{overlap}$。

    正确性证明

    • 必要性:任何合法 tt 若非单一 tt 段型,则必然重复出现,此时所有非 ’a’\text{'a'} 位置的间距是 t|t| 的倍数,所以 t|t| 整除 gg。且 tt 的第一个非 ’a’\text{'a'} 字符一定在位置 LL(因为 LL 是最左非 ’a’\text{'a'}),所以 tt 可以取为 s[L..L+t1]s[L..L+|t|-1]。然后扫描验证必然通过。
    • 充分性:若一个长度 lenlengg 的因子且满足扫描验证,则构造的划分即为合法划分,tt 符合条件。
    • 单一 tt 段型的计数显而易见。
    • 容斥正确去除重叠部分。

    复杂度

    • 计算 gg 及其因子:O(g+m)O(\sqrt{g} + m)gng \le n
    • 对每个因子 lenlen,检查所有非 ’a’\text{'a'} 字符需要 O(m)O(m),扫描整个字符串需要 O(n)O(n)。因子个数通常较小(n=2105n=2\cdot 10^5 时最多约 10310^3),总复杂度 O((m+n)σ(g))O((m+n)\cdot \sigma(g)),在 nn 总和 31053\cdot10^5 下可接受。

    示例验证

    • "aaaaa"\text{"aaaaa"}:全 ’a’\text{'a'},输出 44
    • "baba"\text{"baba"}L=0,R=2,m>1L=0,R=2,m>1g=gcd(2,4)=2g=\gcd(2,4)=2,因子 1,21,2len=1len=1t="b"t=\text{"b"},扫描成功,计入;len=2len=2t="ba"t=\text{"ba"},扫描成功,计入。span_cnt=(0+1)(42)=2\text{span\_cnt}=(0+1)(4-2)=2。重叠:len=23?len=2 \ge 3? 不,2<32<3,无重叠。答案 2+2=42+2=4,正确。

    总结

    本题的关键在于观察到所有非 ’a’\text{'a'} 字符的间距必须具有周期性,t|t| 是这些间距最大公约数的约数,并且 tt 可以从第一个非 ’a’\text{'a'} 字符开始取。同时,包含所有非 ’a’\text{'a'} 字符的连续子串也是合法解。通过枚举 gg 的因子并模拟划分,即可计算所有符合条件的 tt。复杂度在数据范围内可行。

    • 1

    信息

    ID
    6942
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者