【状态压缩】【动态规划】【C++算法】691贴纸拼词

简介: 【状态压缩】【动态规划】【C++算法】691贴纸拼词

作者推荐

视频算法专题

本文涉及知识点

动态规划汇总

状态压缩

LeetCode:691 贴纸拼词

我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。

您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们。如果你愿意,你可以多次使用每个贴纸,每个贴纸的数量是无限的。

返回你需要拼出 target 的最小贴纸数量。如果任务不可能,则返回 -1 。

注意:在所有的测试用例中,所有的单词都是从 1000 个最常见的美国英语单词中随机选择的,并且 target 被选择为两个随机单词的连接。

示例 1:

输入: stickers = [“with”,“example”,“science”], target = “thehat”

输出:3

解释:

我们可以使用 2 个 “with” 贴纸,和 1 个 “example” 贴纸。

把贴纸上的字母剪下来并重新排列后,就可以形成目标 “thehat“ 了。

此外,这是形成目标字符串所需的最小贴纸数量。

示例 2:

输入:stickers = [“notice”,“possible”], target = “basicbasic”

输出:-1

解释:我们不能通过剪切给定贴纸的字母来形成目标“basicbasic”。

提示:

n == stickers.length

1 <= n <= 50

1 <= stickers[i].length <= 10

1 <= target.length <= 15

stickers[i] 和 target 由小写英文单词组成

封装类

假定target串有个n1字符,数量分别为m_vMax[0] m_vMax[1]…m_vMax[n1-1]。

对于某个stickers串,忽略target中没有的字符。target第0 1 2… 个字符在sticker的数量为vNum[0],vNum[1]…

则第0个字符的mask为1*vNum[0]

第1个字符的mask为(m_vMax[0]+1)*vNum[1]

第i个字符的mask为:Mul[ 0 , i − 1 ] j \Large^j_{[0,i-1]}[0,i1]j(vMax[j]+1)*vNum[i]

总mask 为各字符mask之和。

注意: 无论如何vNum[i]都大于等于0,小于等于m_vMax[i]

class CMask
{
public:
  void Add(int iMax)//当前最高位范围[0,iMax]
  {
    m_vMax.emplace_back(iMax);
    m_iMaskCount *= (iMax + 1);
  }
  vector<int> FromMask(int iMask)
  {
    vector<int> vNums;
    for (int i = 0; i < m_vMax.size(); i++)
    {
      vNums.emplace_back(iMask % (m_vMax[i] + 1));
      iMask /= (m_vMax[i] + 1);
    }
    return vNums;
  }
  int ToMask(const vector<int>& vNums,int iMul=1)
  {
    int iMask = 0;
    int iUnit = 1;
    for (int i = 0; i < m_vMax.size(); i++)
    {
      iMask += iUnit * min(m_vMax[i],vNums[i]* iMul);
      iUnit *= (m_vMax[i]+1);
    }
    return iMask;
  }
  int MaskSubVector(int iMask, const vector<int>& vNums, const int iMul = 1)
  {
    int iNewMask = 0;
    int iUnit = 1;
    for (int i = 0; i < m_vMax.size(); i++)
    {
      int cur = iMask % (m_vMax[i] + 1);
      cur -= vNums[i] * iMul;
      cur = max(0, cur);
      iNewMask += iUnit * cur;
      iMask /= (m_vMax[i] + 1);
      iUnit *= (m_vMax[i]+1);
    }
    return iNewMask;
  }
  int NeedGroupCount(const vector<int>& need, const vector<int>& has)
  {
    int iMax = 0;
    for (int i = 0; i < m_vMax.size(); i++)
    {
      if (has[i] <= 0)
      {
        continue;
      }
      iMax = max(iMax,need[i] / has[i]+ (0 != need[i] % has[i]));
    }
    return iMax;
  }
public:
  int MaskCount()const
  {
    return m_iMaskCount;
  } 
  int BitCount()const
  {
    return m_vMax.size();
  }
protected:
  int m_iMaskCount = 1;
  vector<int> m_vMax;
};
class CStrMask : public CMask
{
public:
  CStrMask(const string& target)
  {
    vector<int> vCount;
    for (const auto& ch : target)
    {
      if (mCharToIndex.count(ch))
      {
        vCount[mCharToIndex[ch]]++;
      }
      else
      {
        mCharToIndex[ch] = vCount.size();
        vCount.emplace_back(1);
      }
    }
    for (const auto& cnt : vCount)
    {
      CMask::Add(cnt);
    }
  }
  vector<int> GetVector(const string& s )
  {
    vector<int> vCharNums(m_vMax.size());
    for (const char& ch : s)
    {
      if (mCharToIndex.count(ch))
      {
        auto& i = vCharNums[mCharToIndex[ch]];
        if (i < m_vMax[mCharToIndex[ch]])
        {
          i++;
        }       
      }
    }
    return vCharNums;
  }
protected:
  unordered_map<char, int> mCharToIndex;
private:
  void Add(int iMax) {};
};

动态规划

动态规划的状态表示

pre[iMask] 表示利用前i-1个贴纸,达到未完成的字符状态为iMask的消耗的最少贴纸数。1000表示无法达成。

dp[iMask] 表示利用前i 个贴纸,达到未完成的字符状态为iMask的消耗的最少贴纸数。

动态规划的转移方程

iPreMask 当前贴纸 使用的贴纸数量 如果状态发生变化,则更新状态。

动态规划的填表顺序

对于每个合法的iPreMask,计算当前贴纸最多需要多少份。三层循环:第一层,枚举各贴纸。第二层,枚举pre各状态。第三层:枚举当前贴纸使用的数量。每次处理还要枚举各字符。

故总时间复杂度为:O(50*2151515)

动态规划的初始状态

pre[iMaskCount-1=0 其它值为1000。

动态规划的返回值

pre[0]

代码

核心代码

class Solution {
public:
  int minStickers(vector<string>& stickers, string target) {
    CStrMask mask(target);
    vector<vector<int>> vMaskToCounts(mask.MaskCount());
    for (int i = 0; i < mask.MaskCount(); i++)
    {
      vMaskToCounts[i] = mask.FromMask(i);
    }
    vector<int> vPre(mask.MaskCount(), 1000);
    vPre[mask.MaskCount() - 1] = 0;
    for (const auto s : stickers)
    {
      auto vCharNums = mask.GetVector(s);
      vector<int> dp = vPre;//不选择
      for (int iPre = 0; iPre < mask.MaskCount(); iPre++)
      {
        if (vPre[iPre] >= 1000)
        {
          continue;
        }
        const int iSelMax = mask.NeedGroupCount(vMaskToCounts[iPre], vCharNums);
        for (int iSel = 1; iSel <= iSelMax; iSel++)
        {
          const int iNewMask = mask.MaskSubVector(iPre, vCharNums, iSel);
          dp[iNewMask] = min(dp[iNewMask], vPre[iPre] + iSel);
        }
      }
      vPre.swap(dp);
    }
    return (vPre[0] >= 1000) ? -1 : vPre[0];
  }
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{
  assert(t1 == t2);
}
template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
  if (v1.size() != v2.size())
  {
    assert(false);
    return;
  }
  for (int i = 0; i < v1.size(); i++)
  {
    Assert(v1[i], v2[i]);
  }
}
int main()
{
  
  vector<string> stickers;
  string target;
  {
    Solution sln;
    stickers = { "travel", "quotient", "nose", "wrote", "any" }, target = "lastwest";
    auto res = sln.minStickers(stickers, target);
    Assert(4, res);
  }
  {
    Solution sln;
    stickers = { "with", "example", "science" }, target = "thehat";
    auto res = sln.minStickers(stickers, target);
    Assert(3, res);
  }
  {
    Solution sln;
    stickers = { "notice", "possible" }, target = "basicbasic";
    auto res = sln.minStickers(stickers, target);
    Assert(-1, res);
  }
  {
    Solution sln;
    stickers = { "right", "ten", "year", "share", "period", "paper", "expect", "village", "home", "happen", "ring", "sat", "even", "afraid", "paint", "self", "range", "camp", "note", "read", "paragraph", "run", "basic", "fill", "week", "his", "star", "power", "any", "colony", "object", "free", "dark", "said", "chick", "true", "glad", "child", "room", "lost", "am", "cry", "quiet", "crease", "while", "race", "fun", "found", "dream", "once" }, target = "materialhalf";
    auto res = sln.minStickers(stickers, target);
    Assert(4, res);
  }
  {
    Solution sln;
    stickers = { "indicate","why","finger","star","unit","board","sister","danger","deal","bit","phrase","caught","if","other","water","huge","general","read","gold","shall","master","men","lay","party","grow","view","if","pull","together","head","thank","street","natural","pull","raise","cost","spoke","race","new","race","liquid","me","please","clear","could","reply","often","huge","old","nor" }, target = "fhhfiyfdcwbycma";
    auto res = sln.minStickers(stickers, target);
    Assert(9, res);
  }
  
}

改进简洁版,性能略差

不区分dp pre,因为一个贴纸可以无限使用。无论是pre[iMask]和dp[iMask] 都可增加贴纸。

动态规划的状态表示

状态压缩:如果target第i位已经贴好,则此位为1;否则此位为0。

dp[iMask] 已经完成iMask 消耗的最少贴纸数。

动态规划的转移方程。

对应每个mask,只需要考虑一个当前贴纸。比如: 目标串为aaa,贴纸为a。状态0只考虑一个贴纸。状态1只考虑1个贴纸,总共2个贴纸。状态3只考虑1个贴纸,总共3个贴纸。

如果目标串有多个相同字符,只需要匹配第一字符。“???” 第一张贴纸后,变成"a??" 不需要考虑“?a?"

方案一:第i步匹配第1个a,第j个步匹配第2个a。

方案二:第i步匹配第2个a,第j个步匹配第1个a。

如果方案二,能达到目标,那方案一显然也能达到目标。

iPreMask等于iNewMask 也不用排除,因为新值比旧值大1,必定被淘汰。

class Solution {
public:
  int minStickers(vector<string>& stickers, string target) {
    const int iMaskCount = 1 << target.size();
    vector<int> dp(iMaskCount, 1000);
    dp[0] = 0;
    for (const auto s : stickers)
    {
      int cnt1[26] = { 0 };
      for (const auto& ch : s)
      {
        cnt1[ch - 'a']++;
      }
      for (int iPreMask = 0; iPreMask < iMaskCount; iPreMask++)
      {
        int cnt[26] = { 0 };
        memcpy(cnt, cnt1, sizeof(cnt1));
        int iNewMask = iPreMask;
        for (int j = 0; j < target.size(); j++)
        {
          if (iPreMask & (1 << j))
          {
            continue;//已经拼成
          }
          if (cnt[target[j] - 'a'])
          {
            cnt[target[j] - 'a']--;
            iNewMask |= (1 << j);
          }
        }
        dp[iNewMask] = min(dp[iNewMask], dp[iPreMask] + 1);
      }   
    }
    return (dp.back() >= 1000) ? -1 : dp.back();
  }
};

2023年1月第一版

class Solution {

public:

int minStickers(vector& stickers, string target) {

m_target = target;

for (auto& ch : target)

{

m_mTarget[ch]++;

}

std::unordered_set hasMask;

hasMask.insert(0);

std::unordered_map<int,int> preMaskNum;

preMaskNum[0] = 0;

for (auto& s : stickers)

{

std::unordered_map<char, int> mCur;

for (auto& ch : s)

{

if (m_mTarget.count(ch))

{

mCur[ch]++;

}

}

std::unordered_map<int, int> dp = preMaskNum;

const int iCurMask = MakeMask(mCur);

if (hasMask.count(iCurMask))

{

continue;

}

hasMask.insert(iCurMask);

for (const auto& preMask : preMaskNum )

{

std::unordered_map<char, int> mPre;

ParseMask(mPre, preMask.first);

bool bAdd = true;

int iNum = preMask.second;

while (bAdd)

{

bAdd = false;

for (const auto it : mCur)

{

if (m_mTarget[it.first] > mPre[it.first])

{

bAdd = true;

mPre[it.first] = min(m_mTarget[it.first], mPre[it.first] + mCur[it.first]);

}

}

if (bAdd)

{

iNum++;

const int iMask = MakeMask(mPre);

if (dp.count(iMask))

{

dp[iMask] = min(dp[iMask], iNum);

}

else

{

dp[iMask] = iNum;

}

}

}

}

preMaskNum.swap(dp);

}

int iMaskTargt = MakeMask(m_mTarget);

if (preMaskNum.end() == preMaskNum.find(iMaskTargt))

{

return -1;

}

return preMaskNum[iMaskTargt];

}

int MakeMask(const std::unordered_map<char, int>& nums)const

{

int iMask = 0;

for (const auto& mm : m_mTarget )

{

auto it = nums.find(mm.first);

if ((nums.end() != it) && ( it->second > 0 ))

{

iMask = iMask * (mm.second + 1) + min(mm.second, it->second);

}

else

{

iMask = iMask * (mm.second + 1);

}

}

return iMask;

}

void ParseMask(std::unordered_map<char, int>& nums, int iMask)

{

int iMul = 1;

for (auto& it : m_mTarget)

{

iMul *= (it.second+1);

}

for (auto it = m_mTarget.begin(); it != m_mTarget.end(); ++it)

{

iMul /= (it->second+1);

nums[it->first] = iMask / iMul;

iMask %= iMul;

}

}

std::string m_target;

std::unordered_map<char, int> m_mTarget;

};

2023年1月第2版

class Solution {

public:

int minStickers(vector& stickers, string target) {

m_target = target;

Init();

vector<std::unordered_map<char, int>> mAllCharNum;

{

std::unordered_set hasMask;

hasMask.insert(0);

for (int i = stickers.size() - 1; i >= 0; i–)

{

std::unordered_map<char, int> mCur;

for (auto& ch : stickers[i])

{

if (m_mTarget.count(ch))

{

mCur[ch]++;

}

}

const int iCurMask = MakeMask(mCur);

if (hasMask.count(iCurMask))

{

continue;

}

hasMask.insert(iCurMask);

mAllCharNum.push_back(mCur);

}

}

std::unordered_set setPreMask,setHasDo;

setPreMask.insert(m_iTargetMask);

setHasDo.insert(m_iTargetMask);

for (int iOpeNum = 1; iOpeNum <= target.length(); iOpeNum++)

{

std::unordered_set dp;

for (auto& preMask : setPreMask)

{

std::unordered_map<char, int> mPre;

ParseMask(mPre, preMask);

for (auto& mCur : mAllCharNum)

{

const int iSubMask = GetSubMask(mPre, mCur);

if (0 == iSubMask)

{

continue;

}

const int iNewMask = preMask - iSubMask;

if (setHasDo.count(iNewMask))

{

continue;

}

if (iNewMask == 0 )

{

return iOpeNum;

}

setHasDo.insert(iNewMask);

dp.insert(iNewMask);

}

}

setPreMask.swap(dp);

vector<std::unordered_map<char, int>> mAllTmp;

for (auto& it : setPreMask)

{

std::unordered_map<char, int> tmp;

ParseMask(tmp, it);

mAllTmp.push_back(tmp);

}

}

return -1;

}

int GetSubMask(const std::unordered_map<char, int>& mPre, const std::unordered_map<char, int>& mCur)

{

int iSubMask = 0;

for (auto& cur : mCur)

{

auto pre = mPre.find(cur.first);

if (pre->second )

{

iSubMask += min(pre->second, cur.second) * m_vCharMul[cur.first-‘a’];

}

}

return iSubMask;

}

int MakeMask(const std::unordered_map<char, int>& nums)const

{

int iMask = 0;

for (const auto& mm : m_mTarget )

{

auto it = nums.find(mm.first);

if ((nums.end() != it) && ( it->second > 0 ))

{

iMask = iMask * (mm.second + 1) + min(mm.second, it->second);

}

else

{

iMask = iMask * (mm.second + 1);

}

}

return iMask;

}

void ParseMask(std::unordered_map<char, int>& nums, int iMask)

{

for (auto it = m_mTarget.begin(); it != m_mTarget.end(); ++it)

{

const int iMul = m_vCharMul[it->first-‘a’];

nums[it->first] = iMask / iMul;

iMask %= iMul;

}

}

void Init()

{

for (auto& ch : m_target)

{

m_mTarget[ch]++;

}

m_iTargetMask = MakeMask(m_mTarget);

int iMul = 1;

for (auto& it : m_mTarget)

{

iMul *= (it.second + 1);

}

for (auto it = m_mTarget.begin(); it != m_mTarget.end(); ++it)

{

iMul /= (it->second + 1);

m_vCharMul[it->first - ‘a’] = iMul;

}

}

std::string m_target;

int m_iTargetMask;

std::unordered_map<char, int> m_mTarget;

int m_vCharMul[26] ;

};

2023年1月第三版

class Solution {

public:

int minStickers(vector& stickers, string target) {

m_target = target;

Init();

vector<std::unordered_map<char, int>> mAllCharNum;
   {
     std::unordered_set<int> hasMask;
     hasMask.insert(0);
     for (int i = stickers.size() - 1; i >= 0; i--)
     {
       std::unordered_map<char, int> mCur;
       for (auto& ch : stickers[i])
       {
         if (m_mTarget.count(ch))
         {
           mCur[ch]++;
         }
       }
       const int iCurMask = MakeMask(mCur);
       if (hasMask.count(iCurMask))
       {
         continue;
       }
       hasMask.insert(iCurMask);
       mAllCharNum.push_back(mCur);
     }
   }
  
   std::unordered_set<int> setPreMask,setHasDo;
   setPreMask.insert(m_iTargetMask);
   setHasDo.insert(m_iTargetMask);
   for (int iOpeNum = 1; iOpeNum <= target.length(); iOpeNum++)
   {
     std::unordered_set<int> dp;
     for (auto& preMask : setPreMask)
     {
       std::unordered_map<char, int> mPre;
       ParseMask(mPre, preMask);
       
       char chFristNeedChar = 0;
       for (auto& it : mPre)
       {
         if (it.second > 0)
         {
           chFristNeedChar = it.first;
           break;
         }
       }
       for (auto& mCur : mAllCharNum)
       {
         if ((0 == mCur.count(chFristNeedChar)) || (mCur[chFristNeedChar] <= 0 ))
         {
           continue;
         }
         const int iSubMask = GetSubMask(mPre, mCur);
         if (0 == iSubMask)
         {
           continue;
         }
         const int iNewMask = preMask - iSubMask;
         if (setHasDo.count(iNewMask))
         {
           continue;
         }
         if (iNewMask == 0 )
         {
           return iOpeNum;
         }
         setHasDo.insert(iNewMask);
         dp.insert(iNewMask);
       }
     }
     setPreMask.swap(dp);
     vector<std::unordered_map<char, int>> mAllTmp;
     for (auto& it : setPreMask)
     {
       std::unordered_map<char, int> tmp;
       ParseMask(tmp, it); 
       mAllTmp.push_back(tmp);
     }
   }
   
   
   return -1;
 }
 int GetSubMask(const std::unordered_map<char, int>& mPre, const std::unordered_map<char, int>& mCur)
 {
   int iSubMask = 0;
   for (auto& cur : mCur)
   {
     auto pre = mPre.find(cur.first);
     if (pre->second )
     {
       iSubMask += min(pre->second, cur.second) * m_vCharMul[cur.first-'a'];
     }
   }
   return iSubMask;
 }
 int MakeMask(const std::unordered_map<char, int>& nums)const
 {
   int iMask = 0;
   for (const auto& mm : m_mTarget )
   {
     auto it = nums.find(mm.first);
     if ((nums.end() != it) && ( it->second > 0 ))      
     {
       iMask = iMask * (mm.second + 1) + min(mm.second, it->second);
     }
     else
     {
       iMask = iMask * (mm.second + 1);
     }
   }
   return iMask;
 }
 void ParseMask(std::unordered_map<char, int>& nums, int iMask)
 {
   for (auto it = m_mTarget.begin(); it != m_mTarget.end(); ++it)
   {
     const int iMul = m_vCharMul[it->first-'a'];
     nums[it->first] = iMask / iMul;
     iMask %= iMul;
   }
  
  
 }
 void Init()
 {
   for (auto& ch : m_target)
   {
     m_mTarget[ch]++;
   }
   m_iTargetMask = MakeMask(m_mTarget);
   int iMul = 1;
   for (auto& it : m_mTarget)
   {
     iMul *= (it.second + 1);
   }
   for (auto it = m_mTarget.begin(); it != m_mTarget.end(); ++it)
   {
     iMul /= (it->second + 1);
     m_vCharMul[it->first - 'a'] = iMul;
   }
 }
 std::string m_target;
 int m_iTargetMask;
 std::unordered_map<char, int> m_mTarget;
 int m_vCharMul[26] ;

};

2023年1月 第4版

class CCTestHash

{

public:

std::size_t operator()(const std::unordered_map<char, int>& nums) const

{

return MakeMask(nums);

}

static int MakeMask(const std::unordered_map<char, int>& nums)

{

int iMask = 0;

for (const auto& mm : m_mTarget)

{

auto it = nums.find(mm.first);

if ((nums.end() != it) && (it->second > 0))

{

iMask = iMask * (mm.second + 1) + min(mm.second, it->second);

}

else

{

iMask = iMask * (mm.second + 1);

}

}

return iMask;

}

static void Init()
 {
  m_mTarget.clear();
   for (auto& ch : m_target)
   {
     m_mTarget[ch]++;
   }
   m_iTargetMask = MakeMask(m_mTarget);
   int iMul = 1;
   for (auto& it : m_mTarget)
   {
     iMul *= (it.second + 1);
   }
   for (auto it = m_mTarget.begin(); it != m_mTarget.end(); ++it)
   {
     iMul /= (it->second + 1);
     m_vCharMul[it->first - 'a'] = iMul;
   }
 }
static std::string m_target;
static int m_iTargetMask;
static std::unordered_map<char, int> m_mTarget;
static int m_vCharMul[26];

};

std::string CCTestHash::m_target;

int CCTestHash::m_iTargetMask;

std::unordered_map<char, int> CCTestHash::m_mTarget;

int CCTestHash::m_vCharMul[26];

class Solution {

public:

int minStickers(vector& stickers, string target) {

CCTestHash::m_target = target;

CCTestHash::Init();

std::unordered_set<std::unordered_map<char, int>, CCTestHash> hasMask;
   {       
     for (int i = stickers.size() - 1; i >= 0; i--)
     {
       std::unordered_map<char, int> mCur;
       for (auto& ch : stickers[i])
       {
         if (m_testHask.m_mTarget.count(ch))
         {
           mCur[ch]++;
         }
       }
       if (0 == mCur.size())
       {
         continue;
       }
       if (hasMask.count(mCur))
       {
         continue;
       }
       hasMask.insert(mCur);
     }
   }
  
   std::unordered_set<std::unordered_map<char, int>, CCTestHash> setPreMask, setHasDo;
   setPreMask.insert(CCTestHash::m_mTarget);
   setHasDo.insert(CCTestHash::m_mTarget);
   for (int iOpeNum = 1; iOpeNum <= target.length(); iOpeNum++)
   {
     std::unordered_set<std::unordered_map<char, int>, CCTestHash> dp;
     for (auto& mPre : setPreMask)
     {
       char chFristNeedChar = 0;
       for (auto& it : mPre)
       {
         if (it.second > 0)
         {
           chFristNeedChar = it.first;
           break;
         }
       }
       for (auto& mCur : hasMask)
       {
         if ((0 == mCur.count(chFristNeedChar)) || (mCur.find(chFristNeedChar)->second <= 0 ))
         {
           continue;
         }
         auto newMask = GetSubMask(mPre, mCur);
  
         if (setHasDo.count(newMask))
         {
           continue;
         }
         if (CCTestHash::MakeMask(newMask) == 0)
         {
           return iOpeNum;
         }
         setHasDo.insert(newMask);
         dp.insert(newMask);
       }
     }
     setPreMask.swap(dp);
   }
   
   
   return -1;
 }
 std::unordered_map<char, int> GetSubMask(const std::unordered_map<char, int>& mPre, const std::unordered_map<char, int>& mCur)
 {
   std::unordered_map<char, int> vRet;
   for (auto& pre : mPre)
   {
     auto cur = mCur.find(pre.first);
     if (mCur.end() != cur)
     {
       vRet[pre.first] = max(0, pre.second - cur->second);
     }
     else
     {
       vRet[pre.first] = pre.second;
     }
   }
   return vRet;
 }
 /*
 int MakeMask(const std::unordered_map<char, int>& nums)const
 {
   int iMask = 0;
   for (const auto& mm : m_mTarget )
   {
     auto it = nums.find(mm.first);
     if ((nums.end() != it) && ( it->second > 0 ))      
     {
       iMask = iMask * (mm.second + 1) + min(mm.second, it->second);
     }
     else
     {
       iMask = iMask * (mm.second + 1);
     }
   }
   return iMask;
 }
 void ParseMask(std::unordered_map<char, int>& nums, int iMask)
 {
   for (auto it = m_mTarget.begin(); it != m_mTarget.end(); ++it)
   {
     const int iMul = m_vCharMul[it->first-'a'];
     nums[it->first] = iMask / iMul;
     iMask %= iMul;
   }
  
  
 }
 */
 CCTestHash m_testHask;

};


相关文章
|
17天前
|
机器学习/深度学习 安全 算法
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
|
17天前
|
算法 测试技术 C#
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
|
17天前
|
算法 测试技术 Serverless
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
|
17天前
|
算法 测试技术 C#
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
|
1月前
|
传感器 算法 计算机视觉
基于肤色模型和中值滤波的手部检测算法FPGA实现,包括tb测试文件和MATLAB辅助验证
该内容是关于一个基于肤色模型和中值滤波的手部检测算法的描述,包括算法的运行效果图和所使用的软件版本(matlab2022a, vivado2019.2)。算法分为肤色分割和中值滤波两步,其中肤色模型在YCbCr色彩空间定义,中值滤波用于去除噪声。提供了一段核心程序代码,用于处理图像数据并在FPGA上实现。最终,检测结果输出到&quot;hand.txt&quot;文件。
|
1月前
|
机器学习/深度学习 算法 计算机视觉
基于yolov2深度学习网络的视频手部检测算法matlab仿真
基于yolov2深度学习网络的视频手部检测算法matlab仿真
|
1月前
|
算法
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
23 2
|
1月前
|
算法
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
40 1
|
6天前
|
机器学习/深度学习 人工智能 算法
基于DCT和扩频的音频水印嵌入提取算法matlab仿真
本文介绍了结合DCT和扩频技术的音频水印算法,用于在不降低音质的情况下嵌入版权信息。在matlab2022a中实现,算法利用DCT进行频域处理,通过扩频增强水印的隐蔽性和抗攻击性。核心程序展示了水印的嵌入与提取过程,包括DCT变换、水印扩频及反变换步骤。该方法有效且专业,未来研究将侧重于提高实用性和安全性。
|
10天前
|
文字识别 算法 计算机视觉
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
15 0