Max Dot Product of Two Subsequences

hard dp subsequence

Problem

Given two integer arrays nums1 and nums2, pick a non-empty subsequence from each so that both picks have the same length, then pair them up in order. The score is the dot product: the sum of the element-wise products. Return the maximum score possible.

A subsequence keeps the original order but may skip elements. Arrays have up to 500 elements with values in [−1000, 1000], so negatives matter — sometimes the best you can do is a single least-bad pair.

Inputnums1 = [2,1,-2,5], nums2 = [3,0,-6]
Output18
Pick [2,−2] from nums1 and [3,−6] from nums2: 2·3 + (−2)·(−6) = 6 + 12 = 18.

def max_dot_product(nums1, nums2):
    m, n = len(nums1), len(nums2)
    NEG = float("-inf")
    dp = [[NEG] * (n + 1) for _ in range(m + 1)]
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            p = nums1[i - 1] * nums2[j - 1]
            best = p + max(0, dp[i - 1][j - 1])
            best = max(best, dp[i - 1][j])
            best = max(best, dp[i][j - 1])
            dp[i][j] = best
    return dp[m][n]
function maxDotProduct(nums1, nums2) {
  const m = nums1.length, n = nums2.length;
  const NEG = -Infinity;
  const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(NEG));
  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      const p = nums1[i - 1] * nums2[j - 1];
      let best = p + Math.max(0, dp[i - 1][j - 1]);
      best = Math.max(best, dp[i - 1][j]);
      best = Math.max(best, dp[i][j - 1]);
      dp[i][j] = best;
    }
  }
  return dp[m][n];
}
int maxDotProduct(int[] nums1, int[] nums2) {
    int m = nums1.length, n = nums2.length;
    long NEG = Long.MIN_VALUE / 4;
    long[][] dp = new long[m + 1][n + 1];
    for (long[] row : dp) Arrays.fill(row, NEG);
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            long p = (long) nums1[i - 1] * nums2[j - 1];
            long best = p + Math.max(0, dp[i - 1][j - 1]);
            best = Math.max(best, dp[i - 1][j]);
            best = Math.max(best, dp[i][j - 1]);
            dp[i][j] = best;
        }
    }
    return (int) dp[m][n];
}
int maxDotProduct(vector<int>& nums1, vector<int>& nums2) {
    int m = nums1.size(), n = nums2.size();
    const long long NEG = -1e18;
    vector<vector<long long>> dp(m + 1, vector<long long>(n + 1, NEG));
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            long long p = (long long) nums1[i - 1] * nums2[j - 1];
            long long best = p + max(0LL, dp[i - 1][j - 1]);
            best = max(best, dp[i - 1][j]);
            best = max(best, dp[i][j - 1]);
            dp[i][j] = best;
        }
    }
    return dp[m][n];
}
Time: O(m·n) Space: O(m·n)