题目如下:

思路 or 题解:
对于一个子串, 如果长度为 
    
     
      
       
        l
       
       
        e
       
       
        n
       
      
      
       len
      
     
    len, 如果该子串中任意一个字符的出现个数 大于 
    
     
      
       
        
         
          l
         
         
          e
         
         
          n
         
        
        
         2
        
       
      
      
       \frac{len}{2}
      
     
    2len 那该字符串为 
    
     
      
       
        U
       
       
        n
       
       
        g
       
       
        o
       
       
        o
       
       
        d
       
      
      
       Ungood
      
     
    Ungood 串
 反之,如果任意子串, 长度设为 
    
     
      
       
        l
       
       
        e
       
       
        n
       
      
      
       len
      
     
    len, 如果该子串中任意一个字符的出现个数 小于等于 
    
     
      
       
        
         
          l
         
         
          e
         
         
          n
         
        
        
         2
        
       
      
      
       \frac{len}{2}
      
     
    2len, 那该字符串为 
    
     
      
       
        G
       
       
        o
       
       
        o
       
       
        d
       
      
      
       Good
      
     
    Good 串
核心:
 如果一个子串有字符超过一半,那肯定可以找到一个长度 
    
     
      
       
        ≤
       
       
        3
       
      
      
       \le3
      
     
    ≤3 的子串满足字符超过一半。
我们可以用 DP(动态规划) 的思想去写
 
    
     
      
       
        d
       
       
        p
       
       
        [
       
       
        i
       
       
        ]
       
       
        [
       
       
        j
       
       
        ]
       
       
        [
       
       
        k
       
       
        ]
       
      
      
       dp[i][j][k]
      
     
    dp[i][j][k], 
    
     
      
       
        i
       
      
      
       i
      
     
    i位置, 
    
     
      
       
        i
       
      
      
       i
      
     
    i位置字符为
    
     
      
       
        j
       
      
      
       j
      
     
    j, 
    
     
      
       
        i
       
       
        −
       
       
        1
       
      
      
       i-1
      
     
    i−1位置字符为 
    
     
      
       
        k
       
      
      
       k
      
     
    k 的合法方案数。
转移:
 判断合法,如果合法:
 
    
     
      
       
        d
       
       
        p
       
       
        [
       
       
        i
       
       
        ]
       
       
        [
       
       
        j
       
       
        ]
       
       
        [
       
       
        k
       
       
        ]
       
       
        =
       
       
        (
       
       
        d
       
       
        p
       
       
        [
       
       
        i
       
       
        ]
       
       
        [
       
       
        j
       
       
        ]
       
       
        [
       
       
        k
       
       
        ]
       
       
        +
       
       
        d
       
       
        p
       
       
        [
       
       
        i
       
       
        −
       
       
        1
       
       
        ]
       
       
        [
       
       
        k
       
       
        ]
       
       
        [
       
       
        z
       
       
        ]
       
       
        )
       
      
      
       dp[i][j][k] = (dp[i][j][k] + dp[i - 1][k][z])
      
     
    dp[i][j][k]=(dp[i][j][k]+dp[i−1][k][z])
时间复杂度: O ( n × 2 6 3 ) O(n \times 26^3) O(n×263)
AC 代码如下:
const int mod = 998244353;
const int inf = 2147483647;
const int N = 5009;
int n;
char s[N];
int dp[N][27][27];
bool check(int a, char aa, int b, char bb)
{
    if ((aa != '?' && aa - 'a' != a) || (bb != '?' && bb - 'a' != b))
        return false;
    return true;
}
bool check2(int a, int b, int c)
{
    if (a == b || a == c || b == c)
        return false;
    return true;
}
void solve()
{
    cin >> n;
    cin >> s + 1;
    for (int i = 0; i < 26; i++)
        for (int j = 0; j < 26; j++)
            if (i != j && check(i, s[2], j, s[1]))
                dp[2][i][j] = 1;
        
    for (int i = 3; i <= n; i++)
        for (int j = 0; j < 26; j++)
            for (int k = 0; k < 26; k++)
                for (int z = 0; z < 26; z++)
                {
                    if (!check(j, s[i], k, s[i - 1]) || !check2(j, k, z))
                        continue;
                    dp[i][j][k] = (dp[i][j][k] + dp[i - 1][k][z]) % mod;
                }
    int ans = 0;
    for (int i = 0; i < 26; i++)
        for (int j = 0; j < 26; j++)
            ans = (ans + dp[n][i][j]) % mod;
    cout << ans << '\n';
}
int main()
{
    buff;
    solve();
}

















