Problem p03629 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using db = double;
using ld = long double;
template <typename T> using V = vector<T>;
template <typename T> using VV = vector<vector<T>>;
#define fs first
#define sc second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define all(v) (v).begin(), (v).end()
#define siz(v) (ll)(v).size()
#define rep(i, a, n) for (ll i = a; i < (ll)(n); i++)
#define repr(i, a, n) for (ll i = n - 1; (ll)a <= i; i--)
#define lb lower_bound
#define ub upper_bound
typedef pair<ll, ll> P;
typedef pair<ll, ll> PL;
const ll mod = 1000000007;
const ll INF = 1000000099;
const ll LINF = (ll)(1e18 + 99);
vector<ll> dx = {-1, 1, 0, 0}, dy = {0, 0, -1, 1};
template <typename T, typename U> void chmin(T &t, const U &u) {
  if (t > u)
    t = u;
}
template <typename T, typename U> void chmax(T &t, const U &u) {
  if (t < u)
    t = u;
}
template <typename T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template <typename T> T mpow(T a, T n) {
  T res = 1;
  for (; n; n >>= 1) {
    if (n & 1)
      res = res * a;
    a = a * a;
  }
  return res;
}

int dp[200010] = {};
VV<int> ne;

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(20);

  string s;
  cin >> s;
  int n = siz(s);

  ne = VV<int>(n + 2, V<int>(26, n));

  repr(i, 0, n) {
    rep(j, 0, 26) { ne[i][j] = ne[i + 1][j]; }
    ne[i][s[i] - 'a'] = i;
  }

  dp[n] = 1;
  rep(i, 0, n) dp[i] = INF;

  repr(i, 0, n) {
    rep(j, 0, 26) {
      if (ne[i][j] == n) { //
        dp[i] = 1;
      } else { // 作れない文字列の先頭の文字
        chmin(dp[i], dp[ne[i][j]] + 1);
      }
    }
  }

  string ans = "";
  int ind = 0;
  dp[n] = 0;
  while (ind < n) {
    rep(i, 0, 26) {
      int nind = ne[ind][i] + 1;
      if (dp[ind] - 1 == dp[nind]) {
        ans += 'a' + i;
        ind = min(n, nind);
        break;
      }
      assert(i < 25);
    }
  }
  cout << ans << endl;
}

// dp[i] := i文字目以降で作れない文字列の長さの最小
// ne[i][j] := i文字目以降にある文字jで最も左のindex
//( ・ __ ・ ) KEEP BEING ORGANIZED
// CHECK overflow,vector_size,what to output?

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using db = double;
using ld = long double;
template <typename T> using V = vector<T>;
template <typename T> using VV = vector<vector<T>>;
#define fs first
#define sc second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define all(v) (v).begin(), (v).end()
#define siz(v) (ll)(v).size()
#define rep(i, a, n) for (ll i = a; i < (ll)(n); i++)
#define repr(i, a, n) for (ll i = n - 1; (ll)a <= i; i--)
#define lb lower_bound
#define ub upper_bound
typedef pair<ll, ll> P;
typedef pair<ll, ll> PL;
const ll mod = 1000000007;
const ll INF = 1000000099;
const ll LINF = (ll)(1e18 + 99);
vector<ll> dx = {-1, 1, 0, 0}, dy = {0, 0, -1, 1};
template <typename T, typename U> void chmin(T &t, const U &u) {
  if (t > u)
    t = u;
}
template <typename T, typename U> void chmax(T &t, const U &u) {
  if (t < u)
    t = u;
}
template <typename T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template <typename T> T mpow(T a, T n) {
  T res = 1;
  for (; n; n >>= 1) {
    if (n & 1)
      res = res * a;
    a = a * a;
  }
  return res;
}

int dp[200010] = {};
VV<int> ne;

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(20);

  string s;
  cin >> s;
  int n = siz(s);

  ne = VV<int>(n + 2, V<int>(26, n));

  repr(i, 0, n) {
    rep(j, 0, 26) { ne[i][j] = ne[i + 1][j]; }
    ne[i][s[i] - 'a'] = i;
  }

  dp[n] = 1;
  rep(i, 0, n) dp[i] = INF;

  repr(i, 0, n) {
    rep(j, 0, 26) {
      if (ne[i][j] == n) { //
        dp[i] = 1;
      } else { // 作れない文字列の先頭の文字
        chmin(dp[i], dp[ne[i][j] + 1] + 1); //
      }
    }
  }

  string ans = "";
  int ind = 0;
  dp[n] = 0;
  while (ind < n) {
    rep(i, 0, 26) {
      int nind = ne[ind][i] + 1;
      if (dp[ind] - 1 == dp[nind]) {
        ans += 'a' + i;
        ind = min(n, nind);
        break;
      }
      assert(i < 25);
    }
  }
  cout << ans << endl;
}

// dp[i] := i文字目以降で作れない文字列の長さの最小
// ne[i][j] := i文字目以降にある文字jで最も左のindex
//( ・ __ ・ ) KEEP BEING ORGANIZED
// CHECK overflow,vector_size,what to output?