880. Decoded String at Index

  • 이 문제의 핡심은 λ§Œλ“€μ–΄μ§ˆ λ¬Έμžμ—΄μ—μ„œ prefixλ₯Ό 효과적으둜 μž˜λΌλ‚΄λŠ” 방법을 κ³ λ―Όν•˜λŠ” 데에 μžˆλ‹€.
  • λ¨Όμ € λ¬Έμžμ—΄μ„ ν•΄μ„ν•˜μ—¬ 반볡될 λ¬Έμžμ—΄μ˜ 일뢀 value 와 μ§€κΈˆκΉŒμ§€ λ‚˜μ™”λ˜ pattern을 λ°˜λ³΅ν• νšŸμˆ˜ repeat λ₯Ό κ΅¬ν•˜μ—¬ 각각을 κ΅¬λΆ„λ˜λŠ” ν•­λͺ© Item으둜 λ§Œλ“ λ‹€.
  • 그리고 각 ν•­λͺ©μ˜ λ¬Έμžμ—΄ λ²”μœ„λ₯Ό κ³„μ‚°ν•œλ‹€.
    • 반볡 횟수 repeat κ°€ μ§€μ •λœ ν•­λͺ©μ˜ 경우 from μ—λŠ” μ§€κΈˆκΉŒμ§€μ˜ λ¬Έμžμ—΄ 길이, to μ—λŠ” 반볡된 총 길이λ₯Ό κΈ°λ‘ν•œλ‹€.
    • 반볡될 λ¬Έμžμ—΄μ˜ 일뢀 value κ°€ μ§€μ •λœ ν•­λͺ©μ˜ 경우 fromμ—λŠ” μ§€κΈˆκΉŒμ§€μ˜ λ¬Έμžμ—΄ 길이, to μ—λŠ” value κ°€ 더해진 총 λ¬Έμžμ—΄μ˜ 길이λ₯Ό κΈ°λ‘ν•œλ‹€.
  • λ§ˆμ§€λ§‰μœΌλ‘œ k 값을 0-based index둜 λ³€ν™˜ --k ν•˜κ³  λ‹€μŒ μž‘μ—…μ„ 반볡적으둜 μˆ˜ν–‰ν•œλ‹€.
    • (1) k λ₯Ό ν¬ν•¨ν•˜λŠ” λ²”μœ„ [from, to) λ₯Ό 가진 ν•­λͺ©μ„ μ°ΎλŠ”λ‹€.
    • (2-1) repeatκ°€ μ§€μ •λœ ν•­λͺ©μ΄λΌλ©΄ k μ—μ„œ prefix의 길이 from을 λ‚˜λˆˆ λ‚˜λ¨Έμ§€ k % from λ₯Ό μƒˆλ‘œμš΄ k κ°’μœΌλ‘œ ν•œλ‹€.
      • 검색할 μœ„μΉ˜ k μ•žμ—λŠ” from 길이 만큼의 prefixκ°€ μž„μ˜μ˜ 횟수만큼 반볡될 수 μžˆλ‹€.
      • 이것을 μž˜λΌλ‚΄κ³  λ‚˜λ©΄ μƒˆλ‘œμš΄ index kβ€™λŠ” κ²°κ΅­ prefix λ‚΄λΆ€μ˜ μœ„μΉ˜ν•˜κ²Œ λœλ‹€.
    • (2-2) value κ°€ μ§€μ •λœ ν•­λͺ©μ΄λΌλ©΄ k μ—μ„œ prefix의 길이 from 을 λΊ€ 값을 μƒˆλ‘œμš΄ k κ°’μœΌλ‘œ ν•˜κ³  이λ₯Ό 기반으둜 ν˜„μž¬ ν•­λͺ©μ˜ 값을 μ ‘κ·Ό item.value[k] ν•˜μ—¬ 결과둜 λŒλ €μ€€λ‹€.
      • prefix from 을 μž˜λΌλ‚΄κ³  λ‚˜λ©΄ μƒˆλ‘œμš΄ index k’ λŠ” ν˜„μž¬ ν•­λͺ©μ˜ λ¬Έμžμ—΄ value 내에 μœ„μΉ˜ν•˜κ²Œ λœλ‹€.
class Solution { public: struct Item { string value; int repeat; long long from; long long to; }; string decodeAtIndex(string s, int k) { // make items vector<Item> items; for (auto c : s) { if (c >= '0' && c <= '9') { if (items.empty()) continue; items.push_back({{}, c - '0', 0}); } else { if (items.empty() || items.back().repeat > 0) { items.push_back({}); } items.back().value += c; } } // calculate range long long prevLength = 0; for (auto& item : items) { item.from = prevLength; if (item.repeat > 0) { item.to = prevLength * item.repeat; } else { item.to = prevLength + item.value.length(); } prevLength = item.to; } // to zero based index --k; int pos = 0; while (true) { // find matching range for (int i = 0; i < items.size(); ++i) { if (k >= items[i].from && k < items[i].to) { pos = i; break; } } auto& item = items[pos]; if (item.repeat > 0) { // repeat (remove) prefixes k %= item.from; } else { // remove prefix k -= item.from; // index based on current range return item.value.substr(k, 1); } } // not reachable abort(); } };