The Indian Engineer

Problem 3291 Minimum Number of Valid Strings to Form Target I

Problem Statement

Link - Problem 3291

Question

You are given an array of strings words and a string target.

A string x is called valid if x is a prefix of any string in words.

Return the minimum number of valid strings that can be concatenated to form target. If it is not possible to form target, return -1.

Example 1:

Input: words = ["abc","aaaaa","bcdef"], target = "aabcdabc"

Output: 3

Explanation:

The target string can be formed by concatenating:

  • Prefix of length 2 of words[1], i.e. "aa".
  • Prefix of length 3 of words[2], i.e. "bcd".
  • Prefix of length 3 of words[0], i.e. "abc".

Example 2:

Input: words = ["abababab","ab"], target = "ababaababa"

Output: 2

Explanation:

The target string can be formed by concatenating:

  • Prefix of length 5 of words[0], i.e. "ababa".
  • Prefix of length 5 of words[0], i.e. "ababa".

Example 3:

Input: words = ["abcdef"], target = "xyz"

Output: -1

Constraints:

Solution

class TrieNode {
public:
    vector<TrieNode*> children;
    bool isEnd;

    TrieNode() : children(26, nullptr), isEnd(false) {}
};

class Solution {
private:
    TrieNode* root;

    void insert(const string& word) {
        TrieNode* node = root;
        for (int i = 0; i < word.length(); i++) {
            int index = word[i] - 'a';
            if (!node->children[index]) {
                node->children[index] = new TrieNode();
            }
            node = node->children[index];
            node->isEnd = true;
        }
    }

public:
    int minValidStrings(vector<string>& words, string target) {
        std::ios::sync_with_stdio(false);
        root = new TrieNode();
        for (const string& word : words) {
            insert(word);
        }

        int n = target.length();
        vector<int> dp(n + 1, INT_MAX - 1);
        dp[0] = 0;

        for (int i = 0; i < n; i++) {
            if (dp[i] == INT_MAX - 1)
                continue;

            TrieNode* node = root;
            for (int j = i; j < n; j++) {
                int index = target[j] - 'a';
                if (!node->children[index])
                    break;

                node = node->children[index];
                if (node->isEnd) {
                    dp[j + 1] = min(dp[j + 1], dp[i] + 1);
                }
            }
        }

        return dp[n] == INT_MAX - 1 ? -1 : dp[n];
    }
};

Complexity Analysis

| Algorithm                     | Time Complexity | Space Complexity |
| ----------------------------- | --------------- | ---------------- |
| Dynamic programming with Trie | O(n log m + mn) | O(n)             |

Explanation

Intial Thoughts

Initial approach is to understand the characteristics of the given words and target strings, looking for patterns or prefixes in the words that could match the target. It seems like a problem where we need to find the shortest combination of valid prefixes from the given words to form the target. Using a Trie data structure could be helpful to store the words and efficiently check for prefixes. We also need to consider how to backtrack and try different combinations if the current path does not lead to the target.

Intuitive Analysis

Intuitively, we can think of this problem as a dynamic programming problem where we build up a solution from smaller sub-problems. We start with an empty target and gradually build it up by trying to match prefixes from the given words. We need to keep track of the minimum number of valid strings required to form the target so far. If we reach the end of the target and we have a valid combination, we can return the count. If not, we need to backtrack and try different combinations. This process can be optimized using a Trie data structure to efficiently store and retrieve prefixes.

1. Intuition

2. Implementation


Complexity Analysis

Time Complexity:

Space Complexity:


Footnote

This question is rated as Medium difficulty.

Hints

Let dp[i] be the minimum cost to form the prefix of length i of target.

If target[(i + 1)..j] matches any prefix, update the range dp[(i + 1)..j] to minimum between original value and dp[i] + 1.

Use a Trie to check prefix matching.


Similar Questions:

Title URL Difficulty
Minimum Cost to Convert String II https://leetcode.com/problems/minimum-cost-to-convert-string-ii Hard
Construct String with Minimum Cost https://leetcode.com/problems/construct-string-with-minimum-cost Hard