fork download
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef pair<int, int> ii;
  7.  
  8. const int INF = 1e9;
  9. const ll LINF = 1e18;
  10.  
  11. const int MOD = 1e9 + 7;
  12. const int N = 5e2 + 5;
  13.  
  14. int n;
  15. string s;
  16.  
  17. int C[N][N]; // C[n][k] = Tổ hợp chập k của n
  18.  
  19. void precompute() {
  20. for (int i = 0; i <= n; i++) {
  21. C[i][0] = 1;
  22. for (int j = 1; j <= i; j++) {
  23. C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
  24. }
  25. }
  26. }
  27.  
  28. // dp(l, r) = Số cách để đưa xâu con s[l..r] về thành xâu rỗng
  29. int memo[N][N];
  30.  
  31. int dp(int l, int r) {
  32. if (l > r) return 1;
  33. if (l == r) return 0;
  34. if (l + 1 == r) return (s[l] == s[r]);
  35. if ((r - l + 1) % 2 == 1) return 0;
  36.  
  37. int& ans = memo[l][r];
  38. if (ans != -1) return ans;
  39.  
  40. ans = 0;
  41. int cnt = (r - l + 1) / 2; // tổng số thao tác cần dùng để xoá đoạn [l, r]
  42. for (int k = l + 1; k <= r; k++) { // s[k] sẽ đứng kề với s[l]
  43. if (s[l] == s[k]) {
  44. int cnt1 = max(0, (k - l - 1) / 2); // tổng số thao tác cần dùng để xoá đoạn [l + 1, k - 1]
  45. // Chỉ có thể xoá cặp (s[l], s[k]) sau khi đã xoá đoạn [l + 1, k - 1]
  46. // Chọn thời điểm xoá đoạn [l + 1, k - 1] và cặp (s[l], s[k])
  47. // Những thời điểm còn lại sẽ là xoá đoạn [k + 1, r]
  48. int ways = C[cnt][cnt1 + 1];
  49. ans += 1ll * ways * dp(l + 1, k - 1) % MOD * dp(k + 1, r) % MOD;
  50. ans %= MOD;
  51. }
  52. }
  53.  
  54. return ans;
  55. }
  56.  
  57. int main() {
  58. ios::sync_with_stdio(false);
  59. cin.tie(nullptr);
  60. cin >> s;
  61. n = s.size();
  62. s = ' ' + s;
  63.  
  64. precompute();
  65.  
  66. memset(memo, -1, sizeof memo);
  67. cout << dp(1, n) << '\n';
  68. }
Success #stdin #stdout 0.01s 5280KB
stdin
aabccb
stdout
3