【状态压缩】【动态规划】【C++算法】691贴纸拼词
作者推荐
【动态规划】【数学】【C++算法】18赛车
本文涉及知识点
状态压缩 动态规划
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,i−1]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;
};

扩展阅读
视频课程
有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快
速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
相关下载
想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
| 我想对大家说的话 |
|---|
| 闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
| 如果程序是一条龙,那算法就是他的是睛 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

相关文章:
【状态压缩】【动态规划】【C++算法】691贴纸拼词
作者推荐 【动态规划】【数学】【C算法】18赛车 本文涉及知识点 状态压缩 动态规划 LeetCode:691 贴纸拼词 我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。 您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们。如…...
JavaEE之多线程编程:3. 线程的状态(易懂!)
文章目录 一、关于线程的状态二、观察线程的所有状态1. NEW状态2. TERMINATED状态3. RUNNABLE状态4. TIMED_WAITING 一、关于线程的状态 进程最核心的状态,一个是就绪状态,一个是阻塞状态(对于线程同样使用)。 以线程为单位进行调…...
Android13预装APP到data分区
修改步骤与Android11是差不多的,只是有部分代码所在位置不一样。 Android 11内置APP到data/app Android 8(O)预置APP到data/app 默认内置应用到data会出错 1970-01-01 08:03:54.499 1177-1177/system_process I/PackageManager: /data/app/xx changed; collecting…...
Docker registry镜像仓库,私有仓库及harbor管理详解
目录 registry镜像仓库概述 Docker 镜像仓库(Docker Registry): registry 容器: 私有仓库概述 搭建本地私有仓库示例 Harbor概述 harbor架构 详解构成 Harbor由容器构成 Harbor部署示例 环境准备 部署Docker-Compose服…...
用 Rust 过程宏魔法简化 SQL 函数实现
#[function("length(varchar) -> int4")] pub fn char_length(s: &str) -> i32 {s.chars().count() as i32 }这是 RisingWave 中一个 SQL 函数的实现。只需短短几行代码,通过在 Rust 函数上加一行过程宏,我们就把它包装成了一个 SQL…...
OpenSource - 基于 DFA 算法实现的高性能 java 敏感词过滤工具框架
文章目录 sensitive-word创作目的特性变更日志更多资料敏感词控台敏感词标签文件 快速开始准备Maven 引入核心方法判断是否包含敏感词返回第一个敏感词返回所有敏感词默认的替换策略指定替换的内容自定义替换策略 IWordResultHandler 结果处理类使用实例 更多特性样式处理忽略大…...
端杂七杂八系列篇四-Java8篇
后端杂七杂八系列篇四-Java8篇 ① Lombok插件① RequiredArgsConstructor② SneakyThrows③ UtilityClass④ Cleanup ② Lambda 4个常用的内置函数① Function<T, R> - 接受一个输入参数并返回一个结果② Consumer - 接受一个输入参数,并执行某种操作…...
操作系统一些面试
你这个请求队列是属于一写多读对吧,怎么解决冲突的? 可以采用双buffer或者说双缓冲区,一个缓冲区用来写,一个缓冲区用来读,采用交换指针的方法来进行缓存区的交换,这样交换效率是O(1)的,但是交…...
大语言模型
概念 大语言模型(Large Language Model,简称LLM)是一种基于人工智能技术的自然语言处理模型,是指在大量数据上训练的高级人工智能算法,以自上文推理词语概率为核心任务。它通过在海量文本数据上进行训练,学…...
php反序列化之pop链构造(基于重庆橙子科技靶场)
常见魔术方法的触发 __construct() //创建类对象时调用 __destruct() //对象被销毁时触发 __call() //在对象中调用不可访问的方法时触发 __callStatic() //在静态方式中调用不可访问的方法时触发 __get() //调用类中不存在变量时触发(找有连续箭头的…...
k8s---对外服务 ingress
目录 目录 目录 ingress与service ingress的组成 ingress-controller: ingress暴露服务的方式 2.方式二:DaemonSethostnetworknodeSelector DaemonSethostnetworknodeSelector如何实现 3.deploymentNodePort: 虚拟主机的方式实现http代…...
最优解-最长公共子序列
问题描述 最长公共子序列(Longest Common Subsequence,LCS)即求两个序列最长的公共子序列(可以不连续)。比如3 2 1 4 5和1 2 3 4 5两个序列,最长公共子序列为2 4 5 长度为3。解决这个问题必然要使用动态规划。既然要用到动态规划,就要知道状…...
el-tree获取当前选中节点及其所有父节点的id(包含半选中父节点的id)
如下图,我们现在全勾中的有表格管理及其下的子级,而半勾中的有工作台和任务管理及其子级 现在点击保存按钮后,需要将勾中的节点id及该节点对应的父节点,祖先节点的id(包含半选中父节点的id)也都一并传给后端,那这个例子里就应该共传入9个id,我们可以直接将getCheckedK…...
新上线一个IT公司微信小程序
项目介绍 项目背景: 一家IT公司,业务包含以下六大块: 1、IT设备回收 2、IT设备租赁 3、IT设备销售 4、IT设备维修 5、IT外包 6、IT软件开发 通过小程序,提供在线下单,在线制单,在线销售,业务介绍,推广,会员 项目目的: 业务介绍: 包含企业业务介绍 客户需…...
MCAL配置-PWM(EB23.0)
PWM配置项的介绍 一、General 1、PwmDeInitApi 从代码中添加/删除Pwm_17_GtmCcu6_Delnit() API。 TRUE:Pwm_17_GtmCcu6_Delnit() API可供用户使用。 FALSE:Pwm_17_GtmCcu6_Delnit() API对用户不可用。 注意:默认情况下禁用Pwm_17_GtmCcu6_Delnit() …...
v-if和v-for哪个优先级更高?
v-if和v-for哪个优先级更高? 结论: vue2输出的渲染函数是先执行循环,在看条件判断,如果将v-if和v-for写在一个标签内,哪怕只渲染列表中的一小部分,也要重新遍历整个列表,无形造成资源浪费。vu…...
Mapstruct 常用案例(持续更新.).
将A转换为B Mapper(componentModel "spring") public interface DemoConvert {B A2B(A a); }将List转换为List 注意:以下两个都不可缺少,需要先声明单个和集合的同时生命才可 Mapper(componentModel "spring") public interface …...
QT基础篇(10)QT5网络与通信
QT5网络与通信是指在QT5开发环境中使用网络进行数据传输和通信的相关功能和技术。 QT5提供了一套完善的网络模块,包括了TCP、UDP、HTTP等协议的支持,可以方便地在QT应用程序中进行网络通信。通过QT5的网络模块,开发者可以实现客户端和服务器…...
【Leetcode】269.火星词典(Hard)
一、题目 1、题目描述 现有一种使用英语字母的火星语言,这门语言的字母顺序与英语顺序不同。 给你一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。 请你根据该词典还原出此语言中已知的字母顺序,并 按字母递增顺序…...
opencv_模型训练
文件夹 opencv训练文件 xml negdataposdata 说明 negdata目录: 放负样本的目录 posdata目录: 放正样本的目录 xml目录: 新建的一个目录,为之后存放分类器文件使用 neg.txt: 负样本路径列表 pos.txt: 正样本路径列表 pos.vec: 后续自动生成…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
