1 条题解

  • 0
    @ 2026-4-1 15:22:28

    问题重述

    给定一个长度为偶数 nn 的字符串 ss,求将其分割成若干子串 p1,p2,,pkp_1, p_2, \dots, p_kkk 为偶数)的方案数,使得子串序列是回文的,即:

    pi=pki+1,1ikp_i = p_{k-i+1}, \quad \forall 1 \le i \le k

    答案对 109+710^9+7 取模。


    核心转化

    1. 构造新字符串 tt

    n=sn = |s| 为偶数。定义新字符串 tt 如下:

    $$t = s[0]\,s[n-1]\,s[1]\,s[n-2]\,s[2]\,s[n-3] \dots s[n/2-1]\,s[n/2] $$

    即将 ss 的首尾交替取出,构成新串 tt

    例如,s="abcdcdab"s = \text{"abcdcdab"}n=8n=8

    • s[0]=as[0]=a, s[7]=bs[7]=b, s[1]=bs[1]=b, s[6]=cs[6]=c, s[2]=cs[2]=c, s[5]=ds[5]=d, s[3]=ds[3]=d, s[4]=cs[4]=c
    • 得到 t="abbccddc"t = \text{"abbccddc"}

    2. 转化后的等价问题

    定理:原问题中 ss 的合法分割与 tt偶数长度回文子串分割一一对应。

    证明

    设原分割为 p1,p2,,pkp_1, p_2, \dots, p_kkk 为偶数),且满足 pi=pki+1p_i = p_{k-i+1}

    考虑对称的一对 pip_ipki+1p_{k-i+1}。设 pi=x1x2xmp_i = x_1 x_2 \dots x_mmmpip_i 的长度),则 pki+1=x1x2xmp_{k-i+1} = x_1 x_2 \dots x_m 相同。

    tt 中,这两个子串对应的部分为:

    x1xmx2xm1xm1x2xmx1x_1 x_m x_2 x_{m-1} \dots x_{m-1} x_2 x_m x_1

    这是一个长度为 2m2m 的回文串(偶数长度)。

    由于整个分割是对称的,tt 会被划分成若干个这样的偶数长度回文子串。

    反之,给定 tt 的一个偶数长度回文子串划分,也可以还原出 ss 的一个合法分割。

    因此,问题转化为:

    求将字符串 tt 分割成若干个偶数长度回文子串的方案数。


    动态规划设计

    dp[i]dp[i] 表示前缀 t[1..i]t[1..i] 的合法分割方案数(ii11nnnn 为偶数)。

    边界条件

    dp[0]=1dp[0] = 1

    表示空串有一种分割方式。

    转移方程

    对于 i1i \ge 1,如果 ii 是奇数,则无法分成偶数长度回文子串(因为总长度是奇数,而每个子串长度是偶数),所以:

    dp[i]=0若 i 为奇数dp[i] = 0 \quad \text{若 } i \text{ 为奇数}

    对于偶数 ii,考虑最后一段子串 t[j+1..i]t[j+1..i],它必须是偶数长度回文串。那么:

    $$dp[i] = \sum_{\substack{j < i \\ i-j \text{ 为偶数} \\ t[j+1..i] \text{ 是回文}}} dp[j] $$

    直接枚举所有 jj 的复杂度是 O(n2)O(n^2),不可行。我们需要快速找到所有使得 t[j+1..i]t[j+1..i] 是回文串的 jj


    快速求所有回文后缀

    对于每个位置 ii,我们需要知道所有以 ii 结尾的回文子串的起始位置。

    方法一:回文自动机(Eertree)

    回文自动机(Eertree)可以在 O(n)O(n) 时间内构建,并维护每个位置的所有回文后缀。具体地:

    • 每个节点代表一个回文串
    • 通过后缀链接可以遍历所有以当前位置结尾的回文串

    对于偶数长度回文串,我们只需要考虑长度为偶数的节点。

    pos[i]pos[i] 表示以 ii 结尾的所有偶数长度回文串的起始位置集合,则:

    dp[i]=startpos[i]dp[start1]dp[i] = \sum_{start \in pos[i]} dp[start-1]

    通过 Eertree 可以在 O(n)O(n) 内完成转移,总复杂度 O(n)O(n)


    方法二:Manacher + 差分优化(O(nlogn)O(n \log n)

    另一种方法是利用 Manacher 算法求出每个位置的最长回文半径,然后通过差分数组快速更新 dpdp 值。

    rad[i]rad[i] 表示以 ii 为中心的最长回文半径(包括中心),则:

    • 对于奇数长度回文中心 ii,回文半径为 rad[i]rad[i],对应回文串长度为 2rad[i]12 \cdot rad[i] - 1(奇数),我们不需要
    • 对于偶数长度回文中心 iii+1i+1 之间,回文半径为 rad[i]rad[i],对应回文串长度为 2rad[i]2 \cdot rad[i](偶数)

    对于每个偶数长度回文中心,设其覆盖的起始位置为 jj,则对于所有满足 start[j,j+rad[i]1]start \in [j, j+rad[i]-1] 的位置,都可以从 dp[start1]dp[start-1] 转移到 dp[start+2rad[i]1]dp[start+2 \cdot rad[i]-1]

    这可以用差分数组在 O(n)O(n) 内处理。


    算法步骤(基于 Eertree)

    1. 构造 tt:根据 ss 交替取首尾字符得到 tt,长度为 nn
    2. 构建回文自动机
      • 每个节点存储:长度 lenlen,后缀链接 linklink,转移边 next[c]next[c]
      • 额外维护 evenLinkevenLink 指向最近的长度为偶数的回文后缀(或直接判断 lenlen 是否为偶数)
    3. 动态规划
      • 初始化 dp[0]=1dp[0] = 1
      • 遍历 ii11nn
        • 如果 ii 为奇数,dp[i]=0dp[i] = 0
        • 否则,在回文自动机上沿着后缀链接遍历所有以 ii 结尾的回文串:
          • 若当前回文串长度为偶数,设其起始位置为 start=ilen+1start = i - len + 1,则 dp[i]+=dp[start1]dp[i] \mathrel{+}= dp[start-1]
    4. 答案即为 dp[n]mod(109+7)dp[n] \bmod (10^9+7)

    复杂度分析

    • 构建 ttO(n)O(n)
    • 构建回文自动机:O(n)O(n)
    • 动态规划:每个字符最多访问 O(logn)O(\log n) 个后缀链接(均摊 O(1)O(1)),总复杂度 O(n)O(n)

    因此总复杂度 O(n)O(n),空间复杂度 O(n)O(n)


    • 1

    信息

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