AOJ2680 LR

問題
LR | Aizu Online Judge

'L', 'R', '?', '数字', ',' で構成された文字列が与えられる。L(x, y) = x, R(x, y) = y であるとき、文字列の出力を最大化せよ。
また、正しい数または式が生成できない場合はinvalidとせよ。
文字列長 <= 50


解答
'?'に数字を埋める場合は全て'9'で埋めれば良い。与えられた文字列の部分文字列S[l...r]は、必ず数字またはL(x, y)またはR(x, y)の式である。よって、S[l..r] = "数", "L...)", "R...)"となるように区間DPすれば良い。再帰の基底は部分文字列が数となる場合で、部分文字列のすべての文字が'?'または'数字'である場合である。

string const invalid = string(1, '0'-10);
 
struct number {
  string s;
  number() {};
  number(string const& s): s(s) {};
  bool operator < (number const& r) const {
    if (s.size() != r.s.size()) return s.size() < r.s.size();
    return s < r.s;
  }
  bool operator == (const number &x) const {
    return s == x.s;
  }
};
   
ostream& operator << (ostream& ost, number const& r) {
  return ost << r.s;
}
 
string s;
number dp[55][55];
 
string nine(string s) {
  const int n = s.size();
  rep(i, n) if(s[i] == '?') s[i] = '9';
  if(n > 1 && s[0] == '0') return invalid;
  return s;
}
 
#define srange s.begin()+l, s.begin()+r
 
number solve(int l, int r) {
 
  auto& ret = dp[l][r];
  if(!ret.s.empty()) return ret;
 
  ret = invalid;
 
  bool dcheck = 1;
  REP(i, l, r) dcheck &= isdigit(s[i]) || s[i] == '?';
  if(dcheck) return ret = nine(string(srange));
 
  if((s[l] == 'L' || s[l] == 'R' || s[l] == '?') &&
     (s[l + 1] == '(' || s[l + 1] == '?') &&
     (s[r - 1] == ')' || s[r - 1] == '?')) {
    REP(i, l + 3, r - 2) {
      if(s[i] != '?' && s[i] != ',') continue;
      auto L = solve(l + 2, i);
      auto R = solve(i + 1, r - 1);
      if(L == invalid) continue;
      if(R == invalid) continue;
      if(s[l] == 'L' || s[l] == '?') ret = max(ret, L);
      if(s[l] == 'R' || s[l] == '?') ret = max(ret, R);
    }
  }
 
  return ret;
}
 
int main() {
  cin >> s;
  auto r = solve(0, s.size());
  if(r == invalid) cout << "invalid\n";
  else cout << r << endl;
  return 0;
}