classSolution { public: structTrie { int val; Trie* children[26];
Trie(int val) : val(val), children() {} };
Trie* root; vector<int> dp; string target_;
intminimumCost(string target, vector<string>& words, vector<int>& costs){ root = newTrie(-1); target_ = target; int n = words.size(); int size = target.size(); dp.resize(size, -1); for (int i = 0; i < n; i++) { string& word = words[i]; Trie* cur = root; for (char& c : word) { int idx = c - 'a'; if (cur->children[idx] == nullptr) { cur->children[idx] = newTrie(INT_MAX); } cur = cur->children[idx]; } cur->val = min(costs[i], cur->val); } int res = traverse(0); return res == INT_MAX ? -1 : res; }
longtraverse(int index){ if (index == target_.size()) { return0; } if (dp[index] != -1) { return dp[index]; } long res = INT_MAX; Trie* cur = root; for (int i = index; i < target_.size(); i++) { char& c = target_[i]; int idx = c - 'a'; if (cur->children[idx] == nullptr) { break; } if (cur->children[idx]->val != INT_MAX) { res = min(res, cur->children[idx]->val + traverse(i + 1)); } cur = cur->children[idx]; } dp[index] = res; return res; } };
classSolution { public: structHashObj { constint MOD = 1'070'777'777; int n; vector<int> P, H; template<typename Container> HashObj(Container &s, constint BASE){ n = s.size(); P.resize(n + 1); H.resize(n + 1); P[0] = 1; H[0] = 0; for (int i = 1; i <= n; i++) { P[i] = (long)P[i - 1] * BASE % MOD; } // hash(s) = s[0] * base^(n-1) + s[1] * base^(n-2) + ... + s[n-2] * base + s[n-1] for (int i = 1; i <= n; i++) { H[i] = ((long)H[i - 1] * BASE + s[i - 1]) % MOD; } }
intquery(int l, int r){ if (l > r) return0; return (H[r + 1] - (long)H[l] * P[r - l + 1] % MOD + MOD) % MOD; } };
int max_size = 0; vector<int> dp; HashObj* t; map<int, unordered_map<int, int>> m;
intminimumCost(string target, vector<string>& words, vector<int>& costs){ mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); constint BASE = uniform_int_distribution<>(8e8, 9e8)(rng); t = newHashObj(target, BASE); dp.resize(target.size(), INT_MAX / 2); for (int i = 0; i < words.size(); i++) { string word = words[i]; HashObj obj(word, BASE); int n = word.size(); int h = obj.H[n]; if (m[n].contains(h)) { m[n][h] = min(m[n][h], costs[i]); } else { m[n][h] = costs[i]; } } int res = dfs(0); delete t; return res == INT_MAX / 2 ? -1 : res; }
intdfs(int index){ if (index == t->n) { return0; } if (dp[index] != INT_MAX / 2) { return dp[index]; } int res = INT_MAX / 2; for (auto& [len, mc] : m) { if (len + index > t->n) { break; } int h = t->query(index, index + len - 1); if (mc.contains(h)) { res = min(res, mc[h] + dfs(index + len)); } } dp[index] = res; return res; } };