[題解]AT_abc299_f [ABC299F] Square Subsequence

WaterSunHB發表於2024-06-23

思路

首先先考慮弱化版怎麼做,即如何求本質不同子序列數量。

不妨定義 \(dp_{i}\) 在前 \(i\) 位中選,且以 \(i\) 結尾的本質不同子序列數量。

顯然,有(其中 \(nxt_{i,c}\) 表示在 \(i\) 之後,第一次出現 \(c\) 的位置):

\[ dp_{i} \rightarrow dp_{nxt_{i,c}} \]

本題中的 \(TT\) 是由兩個 \(T\) 拼接而成,所以考慮列舉兩個 \(T\) 的起始位置 \(i,j\)

在這裡定義 \(dp_{i,j}\) 表示兩個 \(T\) 分別以 \(i,j\) 結尾的本質不同子序列數量。

再列舉一下兩個 \(T\) 倒數第二個字元的位置,記作 \(l,r\),並且列舉這個字元 \(c\)

那麼,如果想使 \(T\) 繼續延伸,那麼,必須使新擴充套件的字元相同。因此,記 \(nl = nxt_{l,c},nr = nxt_{r,c}\)

根據上述求本質不同子序列數量的狀態轉移方程,可得:

\[ dp_{nl,nr} = dp_{nl,nr} + dp_{l,r} \]

在統計答案的時候,不能直接將所有 \(dp_{i,j}\) 加起來,這樣會導致重複計算。所以,我們令 \(T\) 取最前面的字元。

Code

#include <bits/stdc++.h>  
#define int long long  
#define re register  
  
using namespace std;  
  
const int N = 110,mod = 998244353;  
int n,ans;  
int nxt[N][N],dp[N][N];  
string s;  
  
signed main(){  
    ios::sync_with_stdio(0);  
    cin.tie(0);  
    cout.tie(0);  
    cin >> s;  
    n = s.length();  
    s = ' ' + s;  
    for (re char c = 'a';c <= 'z';c++) nxt[n][c - 'a'] = n + 1;//預處理 nxt   
    for (re int i = n - 1;~i;i--){  
        for (re char c = 'a';c <= 'z';c++) nxt[i][c - 'a'] = nxt[i + 1][c - 'a'];  
        nxt[i][s[i + 1] - 'a'] = i + 1;  
    }  
    for (re int j = 2;j <= n;j++){  
        int i = nxt[0][s[j] - 'a'];  
        if (i >= j) continue;  
        memset(dp,0,sizeof(dp));  
        dp[i][j] = 1;//i,j 顯然合法,貢獻為 1   
        for (re int l = 1;l <= n;l++){  
            for (re int r = l + 1;r <= n;r++){  
                for (re char c = 'a';c <= 'z';c++){  
                    int nl = nxt[l][c - 'a'];  
                    int nr = nxt[r][c - 'a'];  
                    if (nl >= r || nr > n) continue;  
                    dp[nl][nr] = (dp[nl][nr] + dp[l][r]) % mod;  
                }  
            }  
        }  
        for (re int l = 1;l <= n;l++){  
            for (re int r = l + 1;r <= n;r++){  
                if (nxt[l][s[j] - 'a'] == j) ans = (ans + dp[l][r]) % mod;//要取最前面的   
            }  
        }  
    }  
    printf("%lld",ans);  
    return 0;  
}  

相關文章