【做题记录】P9753 [CSP-S 2023] 消消乐

Tags:

  • DP状态设计
  • 观察性质

题目链接

这道题状态设计十分巧妙。

直接转移显然不切实际。我们不妨“消消乐”的性质入手:

如果区间 \([i,j],[j+1,k]\) 都是可消除的,那么 \([i,k]\) 一定也是可消除的。根据此性质,我们设置辅助数组 \(g\) 维护当前字符可以和之前那个字符形成区间并且区间是可消除的。

具体步骤如下:

  • 我们从 \(j=i-1\) 开始,一直往前跳 \(j=g_j -1\),这样如果遇到有一个位置 \(s_j=s_i\) 的话,新的 \(g_i\) 就是 \(j\) 了。

状态的转移:\(f_i=f_{g_i-1}+1\)

最终答案:\(\sum_{i=1}^n f_i\)

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N(2e6+5);
int n,g[N];
ll f[N],ans;
string s;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>s;
    for(int i(1);i<=n;++i){
        for(int j(i-1);j>0;j=g[j]-1){
            if(s[j-1]==s[i-1]){
                g[i]=j;
                break;
            }
        }if(g[i])f[i]=f[g[i]-1]+1,ans+=f[i];
    }cout<<ans;
    return 0;
}
posted @ 2025-10-18 21:50  CASCwty  阅读(4)  评论(0)    收藏  举报