PTA 团体程序设计天梯赛 L3-020 至多删三个字符

$f[i][j]$表示到第$i$个字符,已经删去了$j$个字符的方案数。

显然的转移:

$f[i][j] = f[i - 1][j] + f[i - 1][j - 1]$

但是这样会有重复,我们考虑什么情况会重复。

比如说:'aabab'中的'bab',我们删去'ba',得到'aab',删去'ab'得到'aab',两者是相同的

1 2 3 4 5

a a b a b

我们假设之前的每一位存的都是没有重复的方案数

就刚才的情况,我们发现当我们递推到第$5$个位置的时候,删去第三位和第四位的'ba',但是保留着第五位的'b'

那这种情况和递推到第$3$个位置的时候,保留着第$3$位的'd'是一样的

即:

$f[5][2] = f[2][0]$

$f[5][3] = f[2][1]$

减去这些重复情况,我们就能保证已经递推过来的情况中没有重复情况

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 1000010
 6 int n;
 7 char s[N];
 8 int pos[220];
 9 ll f[N][4];
10 
11 int main()
12 {
13     while (scanf("%s", s + 1) != EOF)
14     {
15         memset(pos, -1, sizeof pos);
16         n = strlen(s + 1);
17         f[0][0] = 1;
18         for (int i = 1; i <= n; ++i)
19         {
20             int d = pos[s[i]];
21             pos[s[i]] = i;
22             f[i][0] = f[i][1] = 1;
23             for (int j = 1; j < 4; ++j)
24             {
25                 f[i][j] += f[i - 1][j];
26                 f[i][j + 1] = f[i - 1][j];
27                 if (d != -1 && j - i + d >= 0)
28                     f[i][j] -= f[d - 1][j - i + d];
29             }
30         }
31         printf("%lld\n", f[n][0] + f[n][1] + f[n][2] + f[n][3]);
32     }
33     return 0;
34 }
View Code

猜你喜欢

转载自www.cnblogs.com/Dup4/p/10584694.html