Dynamic Programming Approach for Finding Smaller Number Substrings

This soluiton addresses the challenge of counting reversible substrings where the reversed version would create a numerically smaller value.

DP Strategy

The dynamic programming approach builds solutions incrementally by comparing substring pairs:

  • For substrings of length 2, directly compare characters
  • For longer substrings, use previously computed results when endpoints are equal
  • The solution progresses from smaller to larger substring lengths

Recurrence Relation


dp[i][j] = {
  true,           if str[i] > str[j]
  false,          if str[i] < str[j]
  dp[i+1][j-1],   if str[i] == str[j]
}

Complexity Analysis

The optimized DP solution achieves O(n²) time complexity, significantly better than the brute-force O(n³) alternative.

Implementation


#include <vector>
#include <string>
using namespace std;

int countReversibleSubstrings(string num) {
    int n = num.length();
    vector<vector<bool>> memo(n, vector<bool>(n, false));
    
    for (int length = 2; length <= n; length++) {
        for (int start = 0; start + length <= n; start++) {
            int end = start + length - 1;
            if (num[start] > num[end]) {
                memo[start][end] = true;
            }
            else if (num[start] == num[end] && end - start >= 2) {
                memo[start][end] = memo[start+1][end-1];
            }
        }
    }
    
    int total = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (memo[i][j]) total++;
        }
    }
    return total;
}

Alternative Implementation


#include <iostream>
using namespace std;

int main() {
    string input;
    cin >> input;
    int size = input.size();
    bool dp[size][size] = {false};
    
    for (int l = 2; l <= size; l++) {
        for (int i = 0; i <= size - l; i++) {
            int j = i + l - 1;
            if (input[i] > input[j]) {
                dp[i][j] = true;
            }
            else if (input[i] == input[j] && l > 2) {
                dp[i][j] = dp[i+1][j-1];
            }
        }
    }
    
    int result = 0;
    for (int i = 0; i < size; i++) {
        for (int j = i + 1; j < size; j++) {
            result += dp[i][j];
        }
    }
    cout << result;
    return 0;
}

Tags: dynamic-programming string-manipulation substrings algorithm-optimization

Posted on Mon, 18 May 2026 08:18:27 +0000 by markl999