Advertisement
AmbushedRaccoon

Leetcode: Code Testcase Test Result Test Result 2977. Minimum Cost to Convert String II

Nov 20th, 2024
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.20 KB | Source Code | 0 0
  1. #include <string>
  2. #include <vector>
  3. #include <optional>
  4. #include <unordered_set>
  5. #include <unordered_map>
  6.  
  7. class Solution
  8. {
  9. public:
  10.     using Type = std::uint64_t;
  11.     using ValueType = std::optional<Type>;
  12.     using Row = std::vector<ValueType>;
  13.     using Graph = std::vector<Row>;
  14.     const ValueType INF = std::nullopt;
  15.  
  16.     long long minimumCost(std::string source,
  17.         std::string target,
  18.         std::vector<std::string>& original,
  19.         std::vector<std::string>& changed,
  20.         std::vector<int>& cost)
  21.     {
  22.         _source = source;
  23.         _target = target;
  24.         fillGraph(original, changed, cost);
  25.  
  26.         auto result = calculate();
  27.         return result ? result.value() : -1;
  28.     }
  29.  
  30.     void fillGraph(const std::vector<std::string>& original,
  31.         const std::vector<std::string>& changed,
  32.         const std::vector<int>& cost)
  33.     {
  34.         std::unordered_set<std::string> nodesSet;
  35.         for (int i = 0; i < original.size(); i++)
  36.         {
  37.             nodesSet.insert(original[i]);
  38.             nodesSet.insert(changed[i]);
  39.         }
  40.  
  41.         int index = 0;
  42.         for (const auto& node : nodesSet)
  43.         {
  44.             _nodeIndex[node] = index++;
  45.         }
  46.  
  47.         _graph = Graph(nodesSet.size(), Row(nodesSet.size(), INF));
  48.         for (int i = 0; i < original.size(); i++)
  49.         {
  50.             int fromIndex = _nodeIndex[original[i]];
  51.             int toIndex = _nodeIndex[changed[i]];
  52.  
  53.             ValueType& currentValue = _graph[fromIndex][toIndex];
  54.             if (!currentValue || currentValue > cost[i])
  55.             {
  56.                 currentValue = cost[i];
  57.             }
  58.             _lengths.insert(original[i].size());
  59.         }
  60.         _lengths.insert(1);
  61.  
  62.         floydWarshall();
  63.     }
  64.  
  65.     void floydWarshall()
  66.     {
  67.         for (int k = 0; k < _graph.size(); k++)
  68.         {
  69.             for (int i = 0; i < _graph.size(); i++)
  70.             {
  71.                 for (int j = 0; j < _graph.size(); j++)
  72.                 {
  73.                     auto ik = _graph[i][k];
  74.                     auto ij = _graph[i][j];
  75.                     auto kj = _graph[k][j];
  76.                     if (ik && kj)
  77.                     {
  78.                         if (!ij || ij.value() > ik.value() + kj.value())
  79.                         {
  80.                             _graph[i][j] = ik.value() + kj.value();
  81.                         }
  82.                     }
  83.                 }
  84.             }
  85.         }
  86.     }
  87.  
  88.     ValueType calculate()
  89.     {
  90.         std::vector<ValueType> results = std::vector<ValueType>(_source.size(), INF);
  91.  
  92.         for (int i = 0; i < _source.size(); i++)
  93.         {
  94.             for (const int length : _lengths)
  95.             {
  96.                 ValueType prevValue = getPrev(results, i, length);
  97.                 if (prevValue)
  98.                 {
  99.                     std::string from = _source.substr(i - length + 1, length);
  100.                     std::string to = _target.substr(i - length + 1, length);
  101.                     ValueType currentValue = getCurrentValue(from, to);
  102.                     results[i] = Min(results[i], plus(prevValue, currentValue));
  103.                 }
  104.             }
  105.         }
  106.  
  107.         return *results.crbegin();
  108.     }
  109.  
  110.     ValueType plus(const ValueType& a, const ValueType& b)
  111.     {
  112.         if (!a || !b)
  113.         {
  114.             return INF;
  115.         }
  116.         return a.value() + b.value();
  117.     }
  118.  
  119.     ValueType getCurrentValue(const std::string& from, const std::string& to)
  120.     {
  121.         ValueType currentValue = std::nullopt;
  122.         if (from == to)
  123.         {
  124.             currentValue = 0;
  125.         }
  126.         else
  127.         {
  128.             int i, j;
  129.             if (getIndex(from, i) && getIndex(to, j))
  130.             {
  131.                 currentValue = _graph[i][j];
  132.             }
  133.         }
  134.  
  135.         return currentValue;
  136.     }
  137.  
  138.     bool getIndex(const std::string& key, int& outIndex)
  139.     {
  140.         auto iter = _nodeIndex.find(key);
  141.         if (iter != _nodeIndex.end())
  142.         {
  143.             outIndex = iter->second;
  144.             return true;
  145.         }
  146.         return false;
  147.     }
  148.  
  149.     ValueType getPrev(const std::vector<ValueType>& results, int currentIndex, int length)
  150.     {
  151.         int prevIndex = currentIndex - length;
  152.         if (prevIndex >= 0)
  153.         {
  154.             return results[prevIndex];
  155.         }
  156.         else if (prevIndex == -1)
  157.         {
  158.             return 0;
  159.         }
  160.         return INF;
  161.     }
  162.  
  163.     const ValueType& Min(const ValueType& a, const ValueType& b)
  164.     {
  165.         if (!a)
  166.         {
  167.             return b;
  168.         }
  169.         if (!b)
  170.         {
  171.             return a;
  172.         }
  173.         return std::min(a, b);
  174.     }
  175.  
  176. private:
  177.     std::string _source;
  178.     std::string _target;
  179.     std::unordered_map<std::string, int> _nodeIndex;
  180.     std::unordered_set<int> _lengths;
  181.     Graph _graph;
  182. };
  183.  
  184. class SolutionFast
  185. {
  186. public:
  187.     using Type = std::uint64_t;
  188.     using ValueType = std::optional<Type>;
  189.     using Graph = std::vector<ValueType>;
  190.     const ValueType INF = std::nullopt;
  191.  
  192.     long long minimumCost(std::string& source,
  193.         std::string& target,
  194.         std::vector<std::string>& original,
  195.         std::vector<std::string>& changed,
  196.         std::vector<int>& cost)
  197.     {
  198.         _source = std::move(source);
  199.         _target = std::move(target);
  200.  
  201.         fillGraph(original, changed, cost);
  202.  
  203.         auto result = calculate();
  204.  
  205.         if (!result)
  206.         {
  207.             return -1;
  208.         }
  209.         return result.value();
  210.     }
  211.  
  212.     ValueType& getValue(int i, int j)
  213.     {
  214.         return _graph[i * _nodeIndex.size() + j];
  215.     }
  216.  
  217.     const ValueType& getValue(int i, int j) const
  218.     {
  219.         return _graph[i * _nodeIndex.size() + j];
  220.     }
  221.  
  222.     void fillGraph(const std::vector<std::string>& original,
  223.         const std::vector<std::string>& changed,
  224.         const std::vector<int>& cost)
  225.     {
  226.         std::unordered_set<std::string_view> nodesSet;
  227.         for (int i = 0; i < original.size(); i++)
  228.         {
  229.             nodesSet.insert(original[i]);
  230.             nodesSet.insert(changed[i]);
  231.         }
  232.  
  233.         int index = 0;
  234.         for (const auto& node : nodesSet)
  235.         {
  236.             _nodeIndex[node] = index++;
  237.         }
  238.  
  239.         _graph = Graph(nodesSet.size() * nodesSet.size(), INF);
  240.  
  241.         for (int i = 0; i < original.size(); i++)
  242.         {
  243.             int fromIndex = _nodeIndex[original[i]];
  244.             int toIndex = _nodeIndex[changed[i]];
  245.  
  246.             const ValueType& currentValue = getValue(fromIndex, toIndex);
  247.             if (currentValue && currentValue > cost[i] || (!currentValue))
  248.             {
  249.                 getValue(fromIndex, toIndex) = cost[i];
  250.             }
  251.             _lengths.insert(original[i].size());
  252.         }
  253.  
  254.         _lengths.insert(1);
  255.  
  256.         floyd();
  257.     }
  258.  
  259.     void floyd()
  260.     {
  261.         for (int k = 0; k < _nodeIndex.size(); k++)
  262.         {
  263.             for (int i = 0; i < _nodeIndex.size(); i++)
  264.             {
  265.                 const auto& ik = getValue(i, k);
  266.                 for (int j = 0; j < _nodeIndex.size(); j++)
  267.                 {
  268.                     auto& ij = getValue(i, j);
  269.                     const auto& kj = getValue(k, j);
  270.  
  271.                     if (ik && kj)
  272.                     {
  273.                         if (ij)
  274.                         {
  275.                             if (ij.value() > ik.value() + kj.value())
  276.                             {
  277.                                 ij = ik.value() + kj.value();
  278.                             }
  279.                         }
  280.                         else [[likely]]
  281.                         {
  282.                             ij = ik.value() + kj.value();
  283.                         }
  284.                     }
  285.                 }
  286.             }
  287.         }
  288.     }
  289.  
  290. private:
  291.     ValueType Min(const ValueType& a, const ValueType& b) const
  292.     {
  293.         if (!a)
  294.         {
  295.             return b;
  296.         }
  297.         if (!b)
  298.         {
  299.             return a;
  300.         }
  301.  
  302.         return std::min(a.value(), b.value());
  303.     }
  304.  
  305.     ValueType getPrev(const std::vector<ValueType>& result, int currentIndex, int length) const
  306.     {
  307.         int prevIndex = currentIndex - length;
  308.         if (prevIndex >= 0)
  309.         {
  310.             return result[prevIndex];
  311.         }
  312.         else if (prevIndex == -1)
  313.         {
  314.             return 0;
  315.         }
  316.         return INF;
  317.     }
  318.  
  319.     ValueType plus(ValueType a, ValueType b) const
  320.     {
  321.         if (!a || !b)
  322.         {
  323.             return INF;
  324.         }
  325.         return a.value() + b.value();
  326.     }
  327.  
  328.     bool getIndex(const std::string_view& key, int& outIndex) const
  329.     {
  330.         auto iter = _nodeIndex.find(key);
  331.         if (iter != _nodeIndex.end())
  332.         {
  333.             outIndex = iter->second;
  334.             return true;
  335.         }
  336.         return false;
  337.     };
  338.  
  339.     ValueType getCurrentValue(const std::string_view& from, const std::string_view& to) const
  340.     {
  341.         ValueType currentValue = std::nullopt;
  342.         if (from == to)
  343.         {
  344.             currentValue = 0;
  345.         }
  346.         else
  347.         {
  348.             int i, j;
  349.             if (getIndex(from, i) && getIndex(to, j))
  350.             {
  351.                 currentValue = getValue(i, j);
  352.             }
  353.         }
  354.  
  355.         return currentValue;
  356.     };
  357.  
  358.     ValueType calculate()
  359.     {
  360.         _results = std::vector<ValueType>(_source.size(), INF);
  361.  
  362.         int maxLength = *_lengths.crbegin();
  363.  
  364.         for (int i = 0; i < _source.size(); i++)
  365.         {
  366.             for (const int length : _lengths)
  367.             {
  368.                 ValueType prevValue = getPrev(_results, i, length);
  369.                 if (prevValue)
  370.                 {
  371.                     std::string_view from(_source.data() + (i - length + 1), length);
  372.                     std::string_view to(_target.data() + (i - length + 1), length);
  373.                     ValueType currentValue = getCurrentValue(from, to);
  374.                     _results[i] = Min(_results[i], plus(prevValue, currentValue));
  375.                 }
  376.             }
  377.         }
  378.  
  379.         return *_results.crbegin();
  380.     }
  381.  
  382.     std::string _source;
  383.     std::string _target;
  384.  
  385.     Graph _graph;
  386.     std::set<int> _lengths;
  387.     std::vector<ValueType> _results;
  388.     std::unordered_map<std::string_view, int> _nodeIndex;
  389. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement