#pragma once //Êý¾Ý½á¹¹ºÍËã·¨À©³ä //20191212-2054 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //¿â¹ØÁªÐèÇóÎļþ #include "TypeExtend.h" //ÆäËû¿âÎļþÉùÃ÷ //tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐÍ£¬Ê¹ÓôøcvrefµÄÀàÐÍ´«Èë template struct TupleInvokeReturnType; //tupleÀàÐ͵÷Óú¯Êý£¬±¾ÖÊÉÏÖ»ÒªÄܱ»getº¯Êý²ð½â¼´¿É£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë template inline typename TupleInvokeReturnType::type TupleInvoke(TyFunc &&func, TyTup &&tup); //дÀàÐͶþ½øÖÆÎļþÀà //²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿ class BinWriteFile; //¶ÁÀàÐͶþ½øÖÆÎļþÀà //²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿ class BinReadFile; //¿ìËÙ¼ÆËãÃݴΣ¬×¢Òâ·µ»ØÀàÐͺͻùÀàÐÍÏàͬ template inline constexpr Ty FastPower(Ty base, int power) { return power<0 ? 0 : power==0 ? 1 : (power&1)==0 ? FastPower(base*base, power>>1) : base*FastPower(base*base, power>>1); } //ÍÆËã±ÈÀý±íʾ¾«¶È£¬¼´±ÈÀýÀ©´óµ×ÊýµÄ¼¸´ÎÃÝ¿ÉÒÔ´óÓÚµÈÓÚ»ù×¼±ÈÀý template > inline constexpr typename std::enable_if< std::ratio_greater_equal::value, int >::type RatioPrecision() { return 0; } template > inline constexpr typename std::enable_if< !std::ratio_greater_equal::value, int >::type RatioPrecision() { return RatioPrecision, BaseRatio, CompareRatio>()+1; } //Éú³ÉºóÒ»¸ö×éºÏÊý£¬·µ»ØÊÇ·ñµ½Í· //ÒªÇóË«Ïòµü´úÆ÷£¬¿ÉµÝÔö¡¢ÏàµÈ±È½ÏÖµÀàÐÍ template bool NextCombination(TyIt st, TyIt ed, Ty rangeSt, Ty rangeEd) { auto it= ed, it1= it; //ÕÒÊýÖµ¿Õ϶ for(; it!=st; --it) { it1 = it; -- it1; if(it==ed) { if(!(*it1==rangeEd)) { ++ *it1; break; } } else { auto value = *it1; ++ value; if(!(value==*it)) { *it1 = value; break; } } } //ºóÐø×éºÏÊýµÝÔö bool res = it!=st; if(it!=ed) { if(!res) *it = rangeSt; else { it1 = it; -- it1; *it = *it1; ++ *it; } for(it1=it, ++it; it!=ed; it1=it, ++it) { *it = *it1; ++ *it; } } return res; } //Éú³ÉºóÒ»¸öÅÅÁÐ×éºÏÊý£¬·µ»ØÊÇ·ñµ½Í· //ÒªÇóË«Ïòµü´úÆ÷£¬¿ÉµÝÔö¡¢ÏàµÈ±È½ÏÖµÀàÐÍ template bool NextCombinationPermutation(TyIt st, TyIt ed, Ty rangeSt, Ty rangeEd) { if(!std::next_permutation(st, ed)) { if(!NextCombination(st, ed, rangeSt, rangeEd)) return false; } return true; } //¼ÆÊý¼¯ºÏ½»¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò template::type, typename IteratorRemoveCVRefDerefType::type>, typename TyEqual= GeneralEqualTo::type, typename IteratorRemoveCVRefDerefType::type> > inline size_t SetIntersectionCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) { size_t ret = 0; while(true) { if(st1==ed1 || st2==ed2) break; //Á½Õß¶¼ÓÐ if(funcEqual(*st1, *st2)) { ++st1, ++st2; ++ ret; } //ǰÕßÓУ¬ºóÕßûÓÐ else if(funcLess(*st1, *st2)) { ++ st1; } //ºóÕßÓУ¬Ç°ÕßûÓÐ else { ++ st2; } } return ret; } //¼ÆÊý¼¯ºÏ²¢¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò template::type, typename IteratorRemoveCVRefDerefType::type>, typename TyEqual= GeneralEqualTo::type, typename IteratorRemoveCVRefDerefType::type> > inline size_t SetUnionCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) { size_t ret = 0; while(true) { if(st1==ed1 || st2==ed2) { //ºóÕßÓÐÊ£Óà if(st1==ed1) ret += std::distance(st2, ed2); //ǰÕßÓÐÊ£Óà else ret += std::distance(st1, ed1); break; } //Á½Õß¶¼ÓÐ if(funcEqual(*st1, *st2)) { ++st1, ++st2; ++ ret; } //ǰÕßÓУ¬ºóÕßûÓÐ else if(funcLess(*st1, *st2)) { ++ st1; ++ ret; } //ºóÕßÓУ¬Ç°ÕßûÓÐ else { ++ st2; ++ ret; } } return ret; } //¼ÆÊý¼¯ºÏ²î¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò template::type, typename IteratorRemoveCVRefDerefType::type>, typename TyEqual= GeneralEqualTo::type, typename IteratorRemoveCVRefDerefType::type> > inline size_t SetDifferenceCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) { size_t ret = 0; while(true) { if(st1==ed1 || st2==ed2) { //ºóÕßÓÐÊ£Óà if(st1==ed1) ; //ǰÕßÓÐÊ£Óà else ret += std::distance(st1, ed1); break; } //Á½Õß¶¼ÓÐ if(funcEqual(*st1, *st2)) { ++st1, ++st2; } //ǰÕßÓУ¬ºóÕßûÓÐ else if(funcLess(*st1, *st2)) { ++ st1; ++ ret; } //ºóÕßÓУ¬Ç°ÕßûÓÐ else { ++ st2; } } return ret; } //¼ÆÊý¼¯ºÏ¶Ô³Æ²î¼¯£¬ÏßÐÔ¸´ÔÓ¶È£¬ÒªÇóÒÑÅÅÐò template::type, typename IteratorRemoveCVRefDerefType::type>, typename TyEqual= GeneralEqualTo::type, typename IteratorRemoveCVRefDerefType::type> > inline size_t SetSymmetricDifferenceCount(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) { size_t ret = 0; while(true) { if(st1==ed1 || st2==ed2) { //ºóÕßÓÐÊ£Óà if(st1==ed1) ret += std::distance(st2, ed2); //ǰÕßÓÐÊ£Óà else ret += std::distance(st1, ed1); break; } //Á½Õß¶¼ÓÐ if(funcEqual(*st1, *st2)) { ++st1, ++st2; } //ǰÕßÓУ¬ºóÕßûÓÐ else if(funcLess(*st1, *st2)) { ++ st1; ++ ret; } //ºóÕßÓУ¬Ç°ÕßûÓÐ else { ++ st2; ++ ret; } } return ret; } //²¢²é¼¯£¬Êý×ÖË÷Òý£¬Êý×é½á¹¹£¬¿ÉÒÔΪ¿ÕÀàÐÍ template class IndexDisjointSet { private: //²¢²é¼¯½ÚµãÊý¾Ý½á¹¹ struct Node: public ValueHolder { size_t idxPr;//¸¸Ö¸Õë size_t rank = 0;//ÖÈ£¬Ëã·¨Óà template Node(size_t idx, Ty_S &&...arg_s): ValueHolder(std::forward(arg_s)...), idxPr(idx) { } }; private: std::vector vec;//Êý¾Ý public: //¹¹Ô캯Êý IndexDisjointSet() = default; IndexDisjointSet(const IndexDisjointSet &) = default; IndexDisjointSet &operator =(const IndexDisjointSet &) = default; IndexDisjointSet(IndexDisjointSet &&) = default; IndexDisjointSet &operator =(IndexDisjointSet &&) = default; //¶àÊý¾Ý¹¹Ôì template explicit IndexDisjointSet(size_t size, Ty_S &&...arg_s) { Assign(size, std::forward(arg_s)...); } public: //¶àÊý¾Ý¸³Öµ template IndexDisjointSet &Assign(size_t size, Ty_S &&...arg_s) { for(size_t i=0; i!=size; ++i) Emplace(std::forward(arg_s)...); return *this; } //»ñÈ¡Êý¾Ý typename Node::RefType operator[](size_t idx) { return vec[idx]; } typename Node::ConstRefType operator[](size_t idx) const { return vec[idx]; } //»ñÈ¡´óС size_t Size() const { return vec.size(); } //Çå¿Õ void Clear() { vec.clear(); } //Ìí¼Óµã£¬·µ»Ø¸ù template size_t Emplace(Ty_S &&...arg_s) { size_t root = vec.size(); vec.emplace_back(root, std::forward(arg_s)...); return root; } //Ìí¼ÓµãͬʱÁ¬½Ó£¬·µ»Ø¸ù template size_t EmplaceUnion(size_t idx, Ty_S &&...arg_s) { size_t root = vec.size(); vec.emplace_back(root, std::forward(arg_s)...); return Union(root, idx); } //ÕÒ¸ù½Úµã size_t FindRoot(size_t idx) { if(vec[idx].idxPr!=idx) //ÕÒµÄͬʱÁ¬½Óµ½¸ù vec[idx].idxPr = FindRoot(vec[idx].idxPr); return vec[idx].idxPr; } //ºÏ²¢¼¯ºÏ£¬·µ»Ø¸ù size_t Union(size_t idx1, size_t idx2) { size_t root1 = FindRoot(idx1), root2 = FindRoot(idx2); if(vec[root1].rank<=vec[root2].rank) { //1Á¬µ½2ÉÏ vec[root1].idxPr = root2; if(vec[root1].rank==vec[root2].rank) ++ vec[root2].rank; return root2; } else { //2Á¬µ½1ÉÏ vec[root2].idxPr = root1; return root1; } } //ÈÝÆ÷½Ó¿Ú void Reserve(size_t size) { vec.reserve(size); } size_t Capacity() const { return vec.capacity(); } void ShinkToFit() { return vec.shink_to_fit(); } }; template> class MapDisjointSetNode; //Ê÷Ðβ¢²é¼¯ÀàÐͼòд£¬Ö§³ÖÁ¬½ÓºÍÌí¼Ó»ìÓ㬲¢²é¼¯±êǩΪÊ÷µü´úÆ÷ template> using MapDisjointSet = std::map, TyCom>; //Ê÷Ðβ¢²é¼¯£¬½Úµã½á¹¹£¬½«Æä¸³¸ømapÄ£°åÀàÐÍʹÓà template class MapDisjointSetNode: private ValueHolder { template friend TyIt MapDisjointSetFindRoot(TyIt it); template friend TyIt MapDisjointSetUnion(TyIt it1, TyIt it2); private: typename MapDisjointSet::iterator itPr;//´æ´¢Ö¸Õë size_t rank = 0;//ÖÈ£¬Ëã·¨Óà bool bRoot = true;//¼Ç¼ÊÇ·ñΪ¸ù£¬Îª¸ùʱ²»Ðè±£Ö¤Ö¸ÕëÓÐЧ public: //¹¹Ô캯Êý template MapDisjointSetNode(Ty_S &&...arg_s): ValueHolder(std::forward(arg_s)...) { } //ÒýÓÃԭʼÊý¾Ý typename ValueHolder::RefType Get() { return this->hold; } typename ValueHolder::ConstRefType Get() const { return this->hold; } }; //Ê÷Ðβ¢²é¼¯¾²Ì¬Ëã·¨£¬ÕÒ¸ù½Úµã£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷ template inline TyIt MapDisjointSetFindRoot(TyIt it) { if(it->second.bRoot) return it; else { it->second.itPr = MapDisjointSetFindRoot(it->second.itPr); return it->second.itPr; } } //Ê÷Ðβ¢²é¼¯¾²Ì¬Ëã·¨£¬ºÏ²¢¼¯ºÏ£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷£¬·µ»Ø¸ù template inline TyIt MapDisjointSetUnion(TyIt it1, TyIt it2) { TyIt root1= MapDisjointSetFindRoot(it1), root2= MapDisjointSetFindRoot(it2); if(root1==root2) return root1; if(root1->second.rank<=root2->second.rank) { //1Á¬µ½2ÉÏ root1->second.itPr = root2; root1->second.bRoot = false; if(root1->second.rank==root2->second.rank) ++ root2->second.rank; return root2; } else { //2Á¬µ½1ÉÏ root2->second.itPr = root1; root2->second.bRoot = false; return root1; } } template, typename TyEqual= std::equal_to > class UnordMapDisjointSetNode; //¹þÏ£²¢²é¼¯ÀàÐͼòд£¬Ö§³ÖÁ¬½ÓºÍÌí¼Ó»ìÓ㬲¢²é¼¯±êǩΪÄÚÈÝpairÖ¸Õë template, typename TyEqual= std::equal_to > using UnordMapDisjointSet = std::unordered_map, TyHash, TyEqual>; //¹þÏ£²¢²é¼¯£¬½Úµã½á¹¹£¬½«Æä¸³¸øunordered_mapÄ£°åÀàÐÍʹÓà template class UnordMapDisjointSetNode: private ValueHolder { template friend auto UnordMapDisjointSetFindRoot(TyIt it)-> decltype(&*it); template friend auto UnordMapDisjointSetUnion(TyIt it1, TyIt it2)-> decltype(&*it1); private: typename UnordMapDisjointSet::pointer pPr= nullptr;//´æ´¢Ö¸Õë size_t rank = 0;//ÖÈ£¬Ëã·¨Óà bool bRoot = true;//¼Ç¼ÊÇ·ñΪ¸ù£¬Îª¸ùʱ²»Ðè±£Ö¤Ö¸ÕëÓÐЧ public: //¹¹Ô캯Êý template UnordMapDisjointSetNode(Ty_S &&...arg_s): ValueHolder(std::forward(arg_s)...) { } //ÒýÓÃԭʼÊý¾Ý typename ValueHolder::RefType Get() { return this->hold; } typename ValueHolder::ConstRefType Get() const { return this->hold; } }; //¹þÏ£²¢²é¼¯¾²Ì¬Ëã·¨£¬ÕÒ¸ù½Úµã£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷ template inline auto UnordMapDisjointSetFindRoot(TyIt it)-> decltype(&*it) { if(it->second.bRoot) return &*it; else { auto itRes = UnordMapDisjointSetFindRoot(it->second.pPr); it->second.pPr = &*itRes; return it->second.pPr; } } //¹þÏ£²¢²é¼¯¾²Ì¬Ëã·¨£¬ºÏ²¢¼¯ºÏ£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷£¬·µ»Ø¸ù template inline auto UnordMapDisjointSetUnion(TyIt it1, TyIt it2)-> decltype(&*it1) { auto root1= UnordMapDisjointSetFindRoot(it1), root2= UnordMapDisjointSetFindRoot(it2); if(root1==root2) return root1; if(root1->second.rank<=root2->second.rank) { //1Á¬µ½2ÉÏ root1->second.pPr = root2; root1->second.bRoot = false; if(root1->second.rank==root2->second.rank) ++ root2->second.rank; return root2; } else { //2Á¬µ½1ÉÏ root2->second.pPr = root1; root2->second.bRoot = false; return root1; } } //Æ¥ÅäÊ÷ÄÚ²¿½ÚµãÀàÐÍ£¬Æ½ºâÊ÷ʵÏÖ template struct _TrieTreeNode { using RetDataType = TyData *; using ConstRetDataType = const TyData *; constexpr static bool bIsVoid = false; public: TyData *pData = nullptr; std::map> mapCh;//×ÓÊ÷ public: _TrieTreeNode() = default; ~_TrieTreeNode() { delete pData; } //¿½±´º¯Êý _TrieTreeNode(const _TrieTreeNode &other) { operator =(other); } _TrieTreeNode &operator =(const _TrieTreeNode &other) { if(this!=&other) { //Èô¶Ô·½ÓÐÊý¾Ý if(other.pData) { if(pData) *pData = *other.pData; else Construct(other.data); } //Èô¶Ô·½Ã»Êý¾Ý else { if(pData) { delete pData; pData = nullptr; } } //¿½±´ÆäËûÊý¾Ý mapCh = other.mapCh; } return *this; } //¹¹ÔìÊý¾Ý template void Construct(Ty_S &&...arg_s) { assert(pData==nullptr); pData = new TyData(std::forward(arg_s)...); } //Çå³ýÊý¾Ý void Clear() { delete pData; pData = nullptr; mapCh.clear(); } //»ñÈ¡Êý¾ÝÖ¸Õë static RetDataType GetData(_TrieTreeNode *pt) { if(pt==nullptr) return nullptr; else return pt->pData; } static ConstRetDataType GetData(const _TrieTreeNode *pt) { return GetData((_TrieTreeNode *)pt); } }; template struct _TrieTreeNode { using RetDataType = bool; using ConstRetDataType = bool; constexpr static bool bIsVoid = true; public: bool bData = false;//ÊÇ·ñÓÐÊý¾Ý std::map> mapCh;//×ÓÊ÷ public: //¹¹ÔìÊý¾Ý void Construct() { bData = true; } //Çå³ýÊý¾Ý void Clear() { bData = false; mapCh.clear(); } //»ñÈ¡Êý¾Ý±êÇ© static ConstRetDataType GetData(const _TrieTreeNode *pt) { if(pt==nullptr) return false; else return pt->bData; } }; //Æ¥ÅäÊ÷ÄÚ²¿½ÚµãÀàÐÍ£¬¹þÏ£±íʵÏÖ template struct _UnordTrieTreeNode { using RetDataType = TyData *; using ConstRetDataType = const TyData *; constexpr static bool bIsVoid = false; public: TyData *pData = nullptr; std::unordered_map> mapCh;//×ÓÊ÷ public: _UnordTrieTreeNode() = default; ~_UnordTrieTreeNode() { delete pData; } //¿½±´º¯Êý _UnordTrieTreeNode(const _UnordTrieTreeNode &other) { operator =(other); } _UnordTrieTreeNode &operator =(const _UnordTrieTreeNode &other) { if(this!=&other) { //Èô¶Ô·½ÓÐÊý¾Ý if(other.pData) { if(pData) *pData = *other.pData; else Construct(other.data); } //Èô¶Ô·½Ã»Êý¾Ý else { if(pData) { delete pData; pData = nullptr; } } //¿½±´ÆäËûÊý¾Ý mapCh = other.mapCh; } return *this; } //¹¹ÔìÊý¾Ý template void Construct(Ty_S &&...arg_s) { assert(pData==nullptr); pData = new TyData(std::forward(arg_s)...); } //Çå³ýÊý¾Ý void Clear() { delete pData; pData = nullptr; mapCh.clear(); } //»ñÈ¡Êý¾ÝÖ¸Õë static RetDataType GetData(_UnordTrieTreeNode *pt) { if(pt==nullptr) return nullptr; else return pt->pData; } static ConstRetDataType GetData(const _UnordTrieTreeNode *pt) { return GetData((_UnordTrieTreeNode *)pt); } }; template struct _UnordTrieTreeNode { using RetDataType = bool; using ConstRetDataType = bool; constexpr static bool bIsVoid = true; public: bool bData = false;//ÊÇ·ñÓÐÊý¾Ý std::unordered_map> mapCh;//×ÓÊ÷ public: //¹¹ÔìÊý¾Ý void Construct() { bData = true; } //Çå³ýÊý¾Ý void Clear() { bData = false; mapCh.clear(); } //»ñÈ¡Êý¾Ý±êÇ© static ConstRetDataType GetData(const _UnordTrieTreeNode *pt) { if(pt==nullptr) return false; else return pt->bData; } }; //binfile½Ó¿Ú¸¨Öú£¬¿ÉÒÔ¼æÈݺóÃæµÄAcMachineNode template inline typename std::enable_if::type _BinWriteTrieOrAcNodeAssist(BinWriteFile &bwf, TyNode &node) { uint8_t bData = node.pData!=nullptr; bwf < inline typename std::enable_if::type _BinWriteTrieOrAcNodeAssist(BinWriteFile &bwf, TyNode &node) { bwf <<(uint8_t)node.bData; bwf < inline typename std::enable_if::type _BinReadTrieOrAcNodeAssist(BinReadFile &brf, TyNode &node) { uint8_t bData; brf >>bData; //Èô¶Ô·½ÓÐÊý¾Ý if(bData) { if(node.pData==nullptr) node.Construct(); brf >>*node.pData; } //Èô¶Ô·½Ã»Êý¾Ý else { if(node.pData) { delete node.pData; node.pData = nullptr; } } brf >>node.mapCh; } template inline typename std::enable_if::type _BinReadTrieOrAcNodeAssist(BinReadFile &brf, TyNode &node) { uint8_t bData; brf >>bData; node.bData = bData; brf >>node.mapCh; } //binfile½Ó¿Ú template inline BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeNode &node) { _BinWriteTrieOrAcNodeAssist(bwf, node); return bwf; } template inline BinReadFile &operator >>(BinReadFile &brf, _TrieTreeNode &node) { _BinReadTrieOrAcNodeAssist(brf, node); return brf; } template inline BinWriteFile &operator <<(BinWriteFile &bwf, const _UnordTrieTreeNode &node) { _BinWriteTrieOrAcNodeAssist(bwf, node); return bwf; } template inline BinReadFile &operator >>(BinReadFile &brf, _UnordTrieTreeNode &node) { _BinReadTrieOrAcNodeAssist(brf, node); return brf; } template class _TrieTreeTemplate; //Ê÷ÐÎÆ¥Åä½á¹¹ÉÏÏÂÎÄ template struct _TrieContextTemplate { bool bFirst = true;//¼Ç¼Ê×´ÎÆ¥Åä TyNode *pt;//Ê÷½ÚµãÖ¸Õë TyIt it;//Æ¥Åä´®Ö¸Õë }; template inline _TrieContextTemplate MakeTrieContext(const _TrieTreeTemplate &, TyIt) { return _TrieContextTemplate(); } //Ê÷×´´®Æ¥Åä½á¹¹£¬Ö§³ÖvoidÊý¾Ý template class _TrieTreeTemplate { template friend BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeTemplate &trie); template friend BinReadFile &operator >>(BinReadFile &brf, _TrieTreeTemplate &trie); public: //¸¨ÖúÀàÐÍ using NodeType = TyNode; using RetDataType = typename NodeType::RetDataType; using ConstRetDataType = typename NodeType::ConstRetDataType; private: NodeType *pRoot;//Ê÷¸ù½Úµã public: //Î忽±´ _TrieTreeTemplate(): pRoot(new NodeType) { } ~_TrieTreeTemplate() { delete pRoot; } _TrieTreeTemplate(const _TrieTreeTemplate &other): _TrieTreeTemplate() { operator =(other); } _TrieTreeTemplate(_TrieTreeTemplate &&other): _TrieTreeTemplate() { operator =(std::move(other)); } _TrieTreeTemplate &operator =(const _TrieTreeTemplate &other) { if(this!=&other) { *pRoot = *other.pRoot; } return *this; } _TrieTreeTemplate &operator =(_TrieTreeTemplate &&other) { if(this!=&other) { std::swap(pRoot, other.pRoot); } return *this; } private: //Õҽڵ㸨Öúº¯Êý£¬¿Õ´®¿ÉÒÔÆ¥Åä¿ÕÆ¥Å䣬pNode·µ»ØÆ¥ÅäµÄ½Úµã»ò¿Õ //itSt·µ»ØÆ¥ÅäµÄβºó£¬bShortÕÒµ½¼´½áÊø£¬bBlankÔÊÐí¿ÕÆ¥Å䣬bAdd²éÕÒʱÏòºóÌí¼Ó template static void FindAssist(NodeType *&pNode, TyIt &itSt, TyIt itEd, bool bShort, bool bBlank, bool bAdd) { //ÅжϿÕÖ¸Õë if(pNode==nullptr) return; //ÔÊÐíΪ¿ÕʱµÄ´¦Àí if(bBlank) { //Ìáǰ½áÊøÇÒÆ¥Å䣬»òÒѾ­Ã»ÓÐÆ¥ÅäºóÐø£¬Ôò·µ»Ø³õʼ½Úµã if((bShort && NodeType::GetData(pNode)) || itSt==itEd) return; } //ÈôÌáǰ½áÊøÊ§°ÜÇÒûÓкóÐøÆ¥Å䣬ÔòÈÏΪÕÒ²»µ½ if(itSt==itEd) { pNode = nullptr; } //Ö÷Ñ­»· while(itSt!=itEd) {//µü´úÆ÷½áÊøÔòÌø³ö£¬´Ëʱ·µ»ØÖµÎªÕÒµ½µÄ½Úµã //¸ù¾ÝÌí¼ÓÇé¿öÏòºóµü´ú if(bAdd) pNode = &pNode->mapCh[*itSt]; else { auto itPr = pNode->mapCh.find(*itSt); //²»Ìí¼ÓÇÒÕÒ²»µ½¾Í·µ»Ø¿Õ if(itPr==pNode->mapCh.end()) { pNode = nullptr; break; } pNode = &itPr->second; } ++ itSt; //ÅÐÌáǰ½áÊø£¬´Ëʱµü´úÆ÷ÒѳÉΪβºó if(bShort && NodeType::GetData(pNode)) break; } } public: //Ìí¼ÓÆ¥Å乿Ôò template bool EmplaceRule(TyIt itSt, TyIt itEd, Ty_S &&...arg_s) { NodeType *pNode = pRoot; FindAssist(pNode, itSt, itEd, false, true, true); if(NodeType::GetData(pNode)) return false; pNode->Construct(std::forward(arg_s)...); return true; } //Çå³ý½Úµã void Clear() { pRoot->Clear(); } //Æ¥ÅäÍêÕû´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õë»ò·ñ£¬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖà template std::pair Match(TyIt itSt, TyIt itEd) { NodeType *pNode = pRoot; FindAssist(pNode, itSt, itEd, false, true, false); return std::make_pair(itSt, NodeType::GetData(pNode)); } template std::pair Match(TyIt itSt, TyIt itEd) const { return ((_TrieTreeTemplate *)this)->Match(itSt, itEd); } //µü´úËÑË÷´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖà //ctx³õʼ¸³Ä¬ÈϹ¹Ô죬֮ºóÁ¬ÐøÊ¹ÓôË×÷ΪÖмä¼þ template> typename std::enable_if, TyCtx>::value, std::pair >::type Search(TyIt itSt, TyIt itEd, TyCtx &&ctx= TyCtx()) { bool bBlank = false; if(ctx.bFirst) { ctx.bFirst = false; ctx.pt = pRoot; ctx.it = itSt; bBlank = true;//µÚÒ»´Î¿ÉÒÔÆ¥Åä¿Õ£¬Îª±£Ö¤ÍƽøºóÐø²»ÐÐ } FindAssist(ctx.pt, ctx.it, itEd, true, bBlank, false); return std::make_pair(ctx.it, NodeType::GetData(ctx.pt)); } template> typename std::enable_if, TyCtx>::value, std::pair >::type Search(TyIt itSt, TyIt itEd, TyCtx &&ctx= TyCtx()) const { return ((_TrieTreeTemplate *)this)->Search(itSt, itEd, ctx); } //Æ¥Åä×´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖà template std::pair SearchLong(TyIt itSt, TyIt itEd) { _TrieContextTemplate ctx; //Ê×ÏȲéÕÒÒ»´Î auto ret = Search(itSt, itEd, ctx); //ÈôÕҵõ½Ôò¼ÌÐøÕÒ if(ret.second) { while(true) { auto tmp = Search(itSt, itEd, ctx); if(!tmp.second) break; ret = tmp; } } return ret; } template std::pair SearchLong(TyIt itSt, TyIt itEd) const { return ((_TrieTreeTemplate *)this)->SearchLong(itSt, itEd); } //ÕÒµ½µÚÒ»¸ö template RetDataType Judge(TyIt itSt, TyIt itEd) { return Search(itSt, itEd).second; } template ConstRetDataType Judge(TyIt itSt, TyIt itEd) const { return ((_TrieTreeTemplate *)this)->Judge(itSt, itEd); } //¼ÆÊýÕÒµ½´ÎÊý template size_t Count(TyIt itSt, TyIt itEd) const { _TrieContextTemplate ctx; size_t cnt = 0; for(; ; ++cnt) { if(!Search(itSt, itEd, ctx).second) break; } return cnt; } }; //binfile½Ó¿Ú template inline BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeTemplate &trie) { return bwf <<*trie.pRoot; } template inline BinReadFile &operator >>(BinReadFile &brf, _TrieTreeTemplate &trie) { return brf >>*trie.pRoot; } //¶¨ÒåËÑË÷Ê÷µÄƽºâÊ÷ʵÏÖ template using TrieTree = _TrieTreeTemplate<_TrieTreeNode>; template using TrieContext = _TrieContextTemplate<_TrieTreeNode, TyIt>; //¶¨ÒåËÑË÷Ê÷µÄ¹þÏ£±íʵÏÖ template using UnordTrieTree = _TrieTreeTemplate<_UnordTrieTreeNode>; template using UnordTrieContext = _TrieContextTemplate<_UnordTrieTreeNode, TyIt>; //KMPËÑË÷ÀàÉÏÏÂÎÄ template struct KmpContext { ptrdiff_t cnt = -1;//ÒÑÆ¥ÅäµÄ¸öÊý£¬¸ºÊý±íʾδ³õʼ»¯ TyItP itSub;//Æ¥Åäģʽ´®µÄµü´úλÖà TyItT it;//Îı¾´®Î»Öà TyItT itTFlag;//Îı¾´®¶ÔÆë¿ªÊ¼Î»Öà }; template inline KmpContext MakeKmpContext(TyItT, TyItP) { return KmpContext(); } //KMPËÑË÷Àà class KmpSearcher { std::vector vecSub;//¼Ç¼ÓÒÒÆµÄ³¤¶È£¬µÚiÏî¼Ç¼µÄÊÇÒÑÆ¥Åäi+1¸öºóµÄÒÆ¶¯³¤¶È£¬¼´Ï±êiλÖà public: KmpSearcher() = default; template KmpSearcher(TyIt itSt, TyIt itEd) { Assign(itSt, itEd); } public: //¸³Öµº¯Êý template KmpSearcher &Assign(TyIt itSt, TyIt itEd) { vecSub.resize(std::distance(itSt, itEd)); if(vecSub.empty()) return *this; vecSub[1-1] = 1;//ÈôÒÑÆ¥Åä1¸ö£¬ÔòÓ¦¸ÃÓÒÒÆ1 ptrdiff_t cnt = 0;//ÒÑÆ¥ÅäµÄ¸öÊý auto itSub = itSt;//Æ¥Åäģʽ´®µÄµü´úλÖà ptrdiff_t locate = 1;//µ±Ç°¶ÁÈ¡´®µÄϱê //Ö÷ÌåÑ­»· for(++itSt; itSt!=itEd; ++itSt, ++locate) { while(cnt!=0 && *itSt!=*itSub) { //¸Ä±ä¶ÔÆëλÖúͳ¤¶È std::advance(itSub, -vecSub[cnt-1]); cnt -= vecSub[cnt-1]; } if(*itSt==*itSub) ++ cnt, ++itSub; vecSub[locate] = (locate+1-cnt); } return *this; } //ËÑË÷º¯Êý£¬Ö§³ÖΪ¿ÕÆ¥Å䣬ÈôÕÒµ½µü´úÆ÷Ϊָ¶¨´®£¬Î´ÕÒµ½µü´úÆ÷¾ùΪ´®Î²ºó template> typename std::enable_if, TyCtx>::value, std::pair >::type Search(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd, TyCtx &&ctx= TyCtx()) const { assert(std::distance(itPSt, itPEd)==vecSub.size()); //³õʼ»¯ if(ctx.cnt<0) { ctx.cnt = 0; ctx.it = itTSt; ctx.itSub = itPSt; ctx.itTFlag = itTSt; } //ÅжϿմ®Æ¥Åä if(itPSt==itPEd) { auto ret = std::make_pair(ctx.itTFlag, ctx.it); ++ ctx.it, ctx.itTFlag; return ret; } //Ö÷ÌåÑ­»· for(; ctx.it!=itTEd; ++ctx.it) { while(ctx.cnt!=0 && *ctx.it!=*ctx.itSub) { //¸Ä±ä¶ÔÆëλÖúͳ¤¶È std::advance(ctx.itSub, -vecSub[ctx.cnt-1]); std::advance(ctx.itTFlag, vecSub[ctx.cnt-1]); ctx.cnt -= vecSub[ctx.cnt-1]; } if(*ctx.it==*ctx.itSub) { ++ ctx.cnt, ++ctx.itSub; if(ctx.cnt==vecSub.size()) { //ÏÂÒ»¸öÑ­»·Á¿ ++ ctx.it; auto ret = std::make_pair(ctx.itTFlag, ctx.it); //¸Ä±ä¶ÔÆëλÖúͳ¤¶È std::advance(ctx.itSub, -vecSub[ctx.cnt-1]); std::advance(ctx.itTFlag, vecSub[ctx.cnt-1]); ctx.cnt -= vecSub[ctx.cnt-1]; return ret; } } else ++ ctx.itTFlag; } return std::make_pair(itTEd, itTEd); } //ÅжÏÊÇ·ñÕÒµ½ template bool Judge(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd) const { return Search(itTSt, itTEd, itPSt, itPEd).first!=itTEd; } //¼ÆÊýÕÒµ½´ÎÊý template size_t Conut(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd) const { KmpContext ctx; size_t cnt = 0; for(; ; ++cnt) { if(Search(itTSt, itTEd, itPSt, itPEd, ctx).first==itTEd) break; } return cnt; } }; //AC×Ô¶¯»úÄÚ²¿½ÚµãÀàÐÍ£¬Æ½ºâÊ÷ʵÏÖ template struct _AcMachineNode { using RetDataType = TyData *; using ConstRetDataType = const TyData *; constexpr static bool bIsVoid = false; public: TyData *pData = nullptr; std::map mapCh;//×ÓÊ÷ size_t layer = 0;//µ±Ç°²ã _AcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë _AcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë public: _AcMachineNode() = default; ~_AcMachineNode() { delete pData; } //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë _AcMachineNode(const _AcMachineNode &other) { operator =(other); } _AcMachineNode &operator =(const _AcMachineNode &other) { if(this!=&other) { mapCh = other.mapCh; //Èô¶Ô·½ÓÐÊý¾Ý if(other.pData) { if(pData) *pData = *other.pData; else Construct(other.data); } //Èô¶Ô·½Ã»Êý¾Ý else { if(pData) { delete pData; pData = nullptr; } } //¿½±´ÆäËûÊý¾Ý mapCh = other.mapCh; layer = other.layer; pBack = nullptr; pFind = nullptr; } return *this; } //¹¹ÔìÊý¾Ý template void Construct(Ty_S &&...arg_s) { assert(pData==nullptr); pData = new TyData(std::forward(arg_s)...); } //Çå³ýÊý¾Ý void Clear() { delete pData; pData = nullptr; mapCh.clear(); } //»ñÈ¡Êý¾ÝÖ¸Õë static RetDataType GetData(_AcMachineNode *pt) { if(pt==nullptr) return nullptr; else return pt->pData; } static ConstRetDataType GetData(const _AcMachineNode *pt) { return GetData((_AcMachineNode *)pt); } }; template struct _AcMachineNode { using RetDataType = bool; using ConstRetDataType = bool; constexpr static bool bIsVoid = true; public: bool bData = false;//ÊÇ·ñÓÐÊý¾Ý std::map mapCh;//×ÓÊ÷ size_t layer = 0;//µ±Ç°²ã _AcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë _AcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë public: _AcMachineNode() = default; _AcMachineNode(const _AcMachineNode &other) { operator =(other); } //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë _AcMachineNode &operator =(const _AcMachineNode &other) { if(this!=&other) { bData = other.bData; mapCh = other.mapCh; layer = other.layer; pBack = nullptr; pFind = nullptr; } } //¹¹ÔìÊý¾Ý void Construct() { bData = true; } //Çå³ýÊý¾Ý void Clear() { bData = false; mapCh.clear(); } //»ñÈ¡Êý¾Ý±êÇ© static ConstRetDataType GetData(const _AcMachineNode *pt) { if(pt==nullptr) return false; else return pt->bData; } }; //AC×Ô¶¯»úÄÚ²¿½ÚµãÀàÐÍ£¬¹þÏ£±íʵÏÖ template struct _UnordAcMachineNode { using RetDataType = TyData *; using ConstRetDataType = const TyData *; constexpr static bool bIsVoid = false; public: TyData *pData = nullptr; std::unordered_map mapCh;//×ÓÊ÷ size_t layer = 0;//µ±Ç°²ã _UnordAcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë _UnordAcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë public: _UnordAcMachineNode() = default; ~_UnordAcMachineNode() { delete pData; } //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë _UnordAcMachineNode(const _UnordAcMachineNode &other) { operator =(other); } _UnordAcMachineNode &operator =(const _UnordAcMachineNode &other) { if(this!=&other) { mapCh = other.mapCh; //Èô¶Ô·½ÓÐÊý¾Ý if(other.pData) { if(pData) *pData = *other.pData; else Construct(other.data); } //Èô¶Ô·½Ã»Êý¾Ý else { if(pData) { delete pData; pData = nullptr; } } //¿½±´ÆäËûÊý¾Ý mapCh = other.mapCh; layer = other.layer; pBack = nullptr; pFind = nullptr; } return *this; } //¹¹ÔìÊý¾Ý template void Construct(Ty_S &&...arg_s) { assert(pData==nullptr); pData = new TyData(std::forward(arg_s)...); } //Çå³ýÊý¾Ý void Clear() { delete pData; pData = nullptr; mapCh.clear(); } //»ñÈ¡Êý¾ÝÖ¸Õë static RetDataType GetData(_UnordAcMachineNode *pt) { if(pt==nullptr) return nullptr; else return pt->pData; } static ConstRetDataType GetData(const _UnordAcMachineNode *pt) { return GetData((_UnordAcMachineNode *)pt); } }; template struct _UnordAcMachineNode { using RetDataType = bool; using ConstRetDataType = bool; constexpr static bool bIsVoid = true; public: bool bData = false;//ÊÇ·ñÓÐÊý¾Ý std::unordered_map mapCh;//×ÓÊ÷ size_t layer = 0;//µ±Ç°²ã _UnordAcMachineNode *pBack = nullptr;//»ØËݽڵãÖ¸Õë _UnordAcMachineNode *pFind = nullptr;//²éÕÒÓÐЧ½ÚµãÖ¸Õë public: _UnordAcMachineNode() = default; _UnordAcMachineNode(const _UnordAcMachineNode &other) { operator =(other); } //¿½±´º¯Êý£¬¿½±´ºóÐèÒªÖØÐ¹¹ÔìÖ¸Õë _UnordAcMachineNode &operator =(const _UnordAcMachineNode &other) { if(this!=&other) { bData = other.bData; mapCh = other.mapCh; layer = other.layer; pBack = nullptr; pFind = nullptr; } } //¹¹ÔìÊý¾Ý void Construct() { bData = true; } //Çå³ýÊý¾Ý void Clear() { bData = false; mapCh.clear(); } //»ñÈ¡Êý¾Ý±êÇ© static ConstRetDataType GetData(const _UnordAcMachineNode *pt) { if(pt==nullptr) return false; else return pt->bData; } }; //binfile½Ó¿Ú template inline BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineNode &node) { _BinWriteTrieOrAcNodeAssist(bwf, node); return bwf; } template inline BinReadFile &operator >>(BinReadFile &brf, _AcMachineNode &node) { _BinReadTrieOrAcNodeAssist(brf, node); return brf; } template inline BinWriteFile &operator <<(BinWriteFile &bwf, const _UnordAcMachineNode &node) { _BinWriteTrieOrAcNodeAssist(bwf, node); return bwf; } template inline BinReadFile &operator >>(BinReadFile &brf, _UnordAcMachineNode &node) { _BinReadTrieOrAcNodeAssist(brf, node); return brf; } template class _AcMachineTemplate; //AC×Ô¶¯»úËÑË÷ÀàÉÏÏÂÎÄ template struct _AcContextTemplate { bool bFirst = true;//¼Ç¼Ê×´ÎÆ¥Åä TyNode *pt = nullptr;//Ê÷½ÚµãÖ¸Õë TyNode *pFind = nullptr;//ÕýÔÚ²éÕÒÖ¸Õë TyIt it;//Æ¥Åä´®Ö¸Õë }; template inline _AcContextTemplate MakeAcContext(const _AcMachineTemplate &, TyIt) { return _AcContextTemplate(); } //AC×Ô¶¯»úËÑË÷À֧࣬³ÖvoidÊý¾Ý template class _AcMachineTemplate { template friend BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineTemplate &acm); template friend BinReadFile &operator >>(BinReadFile &brf, _AcMachineTemplate &acm); public: //¸¨ÖúÀàÐÍ using NodeType = TyNode; using RetDataType = typename NodeType::RetDataType; using ConstRetDataType = typename NodeType::ConstRetDataType; private: NodeType *pRoot;//¸ù½Úµã bool bPrepare = true; public: //Î忽±´ _AcMachineTemplate(): pRoot(new NodeType()) { } ~_AcMachineTemplate() { delete pRoot; } _AcMachineTemplate(const _AcMachineTemplate &other): _AcMachineTemplate() { operator =(other); } _AcMachineTemplate(_AcMachineTemplate &&other): _AcMachineTemplate() { operator =(std::move(other)); } _AcMachineTemplate &operator =(const _AcMachineTemplate &other) { if(this!=&other) { *pRoot = *other.pRoot; bPrepare = false; if(other.bPrepare) { bPrepare = false; Prepare(); } } return *this; } _AcMachineTemplate &operator =(_AcMachineTemplate &&other) { if(this!=&other) { std::swap(pRoot, other.pRoot); std::swap(bPrepare, other.bPrepare); } return *this; } public: //×ö×¼±¸£¬ÔÚ½øÐÐÆ¥Åä֮ǰµ÷Óã¬Ò²¿ÉÊÖ¶¯µ÷Óà void Prepare() { if(bPrepare) return; std::deque deqNode;//½ÚµãÕ¹¿ª¶ÓÁÐ //¹¹ÔìµÚÒ»²ã»ØËÝ deqNode.push_back(pRoot); //Õ¹¿ª¶ÓÁÐ while(!deqNode.empty()) { //ÿһ¸ö×Ó½Úµã for(auto &pr: deqNode.front()->mapCh) { //Ìí¼Ó¶ÓÁÐ deqNode.push_back(&pr.second); //ѰÕÒ¸¸½Úµã auto pFindBack = deqNode.front(); while(pFindBack->pBack!=nullptr) { pFindBack = pFindBack->pBack; auto res = pFindBack->mapCh.find(pr.first); if(res!=pFindBack->mapCh.end()) { pFindBack = &res->second; break; } } //¹¹Ô츸ָÕë pr.second.pBack = pFindBack; if(NodeType::GetData(pFindBack)) pr.second.pFind = pFindBack; else pr.second.pFind = pFindBack->pFind; pr.second.layer = deqNode.front()->layer+1; } //µ¯³ö¶ÓÁÐ deqNode.pop_front(); } bPrepare = true; } //Ìí¼ÓÆ¥Å乿Ôò template bool EmplaceRule(TyIt itSt, TyIt itEd, Ty_S &&...arg_s) { bPrepare = false; NodeType *pNode = pRoot; while(itSt!=itEd) { auto res = pNode->mapCh.emplace(std::piecewise_construct, std::tie(*itSt), std::make_tuple()); pNode = &res.first->second; bPrepare = bPrepare && !res.second; ++ itSt; } if(NodeType::GetData(pNode)) return false; pNode->Construct(std::forward(arg_s)...); return true; } //Çå³ý½Úµã void Clear() { pRoot->Clear(); bPrepare = true; } //µü´úËÑË÷º¯Êý£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½·µ»ØÕÒµ½Î²ºóºÍ³¤¶È£¬Î´ÕÒµ½·µ»Ø´®Î²ºóºÍ0 template> typename std::enable_if, TyCtx>::value, std::tuple >::type Search(TyIt itSt, TyIt itEd, TyCtx &&ctx= TyCtx()) { //×¼±¸ Prepare(); //³õʼ»¯ bool bFirst = false; if(ctx.bFirst) { ctx.bFirst = false; ctx.pt = pRoot; ctx.it = itSt; bFirst = true; } auto ret = std::make_tuple(ctx.it, (size_t)0, NodeType::GetData((NodeType *)nullptr)); //ÅжÏÊä³öͬһ½Úµã½á¹û if(ctx.pFind!=nullptr) { std::get<1>(ret) = ctx.pFind->layer; std::get<2>(ret) = NodeType::GetData(ctx.pFind); ctx.pFind = ctx.pFind->pFind; } //ÈôΪµÚÒ»´Î²éÕÒÇÒ´æÔÚ¿ÕÆ¥Åä else if(bFirst && NodeType::GetData(ctx.pt)) { std::get<1>(ret) = ctx.pt->layer; std::get<2>(ret) = NodeType::GetData(ctx.pt); ctx.pFind = ctx.pt->pFind; } //·ñÔò²éÕÒÏÂÒ»½Úµã else { //¶ÁÈë×Ö·ûÑ­»· while(ctx.it!=itEd) { //²éÕÒ»ØËÝ while(true) { auto res = ctx.pt->mapCh.find(*ctx.it); if(res!=ctx.pt->mapCh.end()) { ctx.pt = &res->second; break; } if(ctx.pt->pBack==nullptr) break; ctx.pt = ctx.pt->pBack; } ++ ctx.it; //ÈôÕÒµ½´øÊý¾ÝµÄ½Úµã if(NodeType::GetData(ctx.pt)) { std::get<1>(ret) = ctx.pt->layer; std::get<2>(ret) = NodeType::GetData(ctx.pt); ctx.pFind = ctx.pt->pFind; break; } //ÈôÕÒµ½´ø²éÕÒÊý¾ÝµÄ½Úµã else if(ctx.pt->pFind!=nullptr) { ctx.pFind = ctx.pt->pFind; std::get<1>(ret) = ctx.pFind->layer; std::get<2>(ret) = NodeType::GetData(ctx.pFind); ctx.pFind = ctx.pFind->pFind; break; } } std::get<0>(ret) = ctx.it; } return ret; } //ÕÒµ½µÚÒ»¸ö£¬Æ¥Åäβºó¿¼Ç°ÓÅÏÈ£¬Æ¥ÅäÊײ¿¿¿Ç°ÓÅÏÈ template RetDataType Judge(TyIt itSt, TyIt itEd) { return std::get<2>(Search(itSt, itEd)); } //¼ÆÊýÕÒµ½´ÎÊý template RetDataType Count(TyIt itSt, TyIt itEd) { _AcContextTemplate ctx; size_t cnt = 0; for(; ; ++cnt) { if(std::get<2>(Search(itSt, itEd, ctx))) break; } return cnt; } }; //binfile½Ó¿Ú template inline BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineTemplate &acm) { return bwf <<(uint8_t)acm.bPrepare <<*acm.pRoot; } template inline BinReadFile &operator >>(BinReadFile &brf, _AcMachineTemplate &acm) { uint8_t bPrepare; brf >>bPrepare; acm.bPrepare = false; brf >>*acm.pRoot; if(bPrepare) acm.Prepare(); return brf; } //¶¨ÒåËÑË÷Ê÷µÄƽºâÊ÷ʵÏÖ template using AcMachine = _AcMachineTemplate<_AcMachineNode>; template using AcContext = _AcContextTemplate<_AcMachineNode, TyIt>; //¶¨ÒåËÑË÷Ê÷µÄ¹þÏ£±íʵÏÖ template using UnordAcMachine = _AcMachineTemplate<_UnordAcMachineNode>; template using UnordAcContext = _AcContextTemplate<_UnordAcMachineNode, TyIt>; //Ö»ÄÜÌí¼ÓÔªËØµÄͼ£¬Ö§³ÖvoidÊý¾ÝÀàÐÍ //ÄÚ²¿Îª¶þάÊý×éʵÏÖ //½Úµãµü´úÆ÷ÔÊÐíʹÓÃÕûÐÎË÷Òý¹¹Ôì //ClearºÍAssign»áµ¼Öµü´úÆ÷ʧЧ //ÈÝÆ÷¸´ÖÆ¡¢Òƶ¯¡¢½»»»ºóµü´úÆ÷¾ùÖ¸Ïò¾ÉÈÝÆ÷£¬ÔÊÐíµü´úÆ÷¸üÐÂÈÝÆ÷Ö¸Õë //TODO: Ïë½á¹¹Éè¼Æ£¬³¢ÊÔ½«½ÚµãÓë±ß¶ÔÓ¦µ½ÕûÐÎË÷ÒýÉÏ template class AddonlyGraph { private: //±ß½á¹¹Ìå struct EdgeStruct: public ValueHolder { size_t index;//±ß±àºÅ //½ÓÊÕÊý¾ÝÀàÐÍÄ£°å²ÎÊýµÄ¹¹Ôì template EdgeStruct(size_t o_index, Tys &&...args): ValueHolder(std::forward(args)...), index(o_index) { } }; //½Úµã½á¹¹Ìå struct NodeStruct: public ValueHolder { std::vector vecEdge;//³ö±ßÊý×é //½ÓÊÕ×óÖµ»òÓÒÖµµÄÊý¾Ý¹¹Ôì template NodeStruct(Tys &&...args): ValueHolder(std::forward(args)...) { } }; private://¸¨ÖúÀàÐͶ¨Òå using GraphType = AddonlyGraph;//ͼÀàÐÍ public: using NodeDataType = TyNodeData;//½ÚµãÊý¾ÝÀàÐÍ using EdgeDataType = TyEdgeData;//±ßÊý¾ÝÀàÐÍ private://µü´úÆ÷Ä£°å¶¨Òå //½Úµãµü´úÆ÷Ä£°å¸¨ÖúÀà template class TemplateNodeIterAssist; //½Úµãµü´úÆ÷Ä£°å template class TemplateNodeIter; //±ßµü´úÆ÷Ä£°å¸¨ÖúÀà template class TemplateEdgeIterAssist; //±ßµü´úÆ÷Ä£°å template class TemplateEdgeIter; private://µü´úÆ÷Ä£°åÖ¸¶¨ÀàÐͶ¨Òå //½Úµãµü´úÆ÷¸¨ÖúÀàÖ¸¶¨ using NodeIterAssist = TemplateNodeIter; //½Úµã³£µü´úÆ÷¸¨ÖúÀàÖ¸¶¨ using NodeConstIterAssist = TemplateNodeIter< const GraphType, const TyNodeData, TyNodeData>; //±ßµü´úÆ÷¸¨ÖúÀàÖ¸¶¨ using EdgeIterAssist = TemplateEdgeIter; //±ß³£µü´úÆ÷¸¨ÖúÀàÖ¸¶¨ using EdgeConstIterAssist = TemplateEdgeIter< const GraphType, const TyEdgeData, TyEdgeData>; public: //½Úµãµü´úÆ÷ÀàÖ¸¶¨ using NodeIter = TemplateNodeIter; //½Úµã³£µü´úÆ÷ÀàÖ¸¶¨ using NodeConstIter = TemplateNodeIter< const GraphType, const TyNodeData, const TyEdgeData>; //±ßµü´úÆ÷ÀàÖ¸¶¨ using EdgeIter = TemplateEdgeIter; //±ß³£µü´úÆ÷ÀàÖ¸¶¨ using EdgeConstIter = TemplateEdgeIter< const GraphType, const TyNodeData, const TyEdgeData>; public://ÓÑÔªÉùÃ÷ friend NodeIter; friend NodeIterAssist; friend NodeConstIter; friend NodeConstIterAssist; friend EdgeIter; friend EdgeIterAssist; friend EdgeConstIter; friend EdgeConstIterAssist; private://³ÉÔ±Êý¾Ý std::vector vecNode;//½ÚµãÊý×é public://»ù±¾º¯Êý //ĬÈϹ¹Ôì AddonlyGraph() = default; //¶à¸öÊý¾Ý¹¹Ôì template explicit AddonlyGraph(size_t size, const Ty_S &...arg_s) { Assign(size, arg_s...); } public://³ÉÔ±º¯Êý //¸³Öµº¯Êý template AddonlyGraph &Assign(size_t size, const Ty_S &...arg_s) { vecNode.assign(size, NodeStruct(arg_s...)); return *this; } //Ìí¼Ó½Úµã template typename std::enable_if::value, NodeIter >::type AddNode(TyNodeDataMy &&data) { return EmplaceNode(std::forward(data)); } template NodeIter EmplaceNode(Tys &&...args) { vecNode.emplace_back(std::forward(args)...); return NodeIter(this, vecNode.size()-1); } //Ìí¼Ó±ß template typename std::enable_if::value, EdgeIter >::type AddEdge(NodeIter fromNode, NodeIter toNode, TyEdgeDataMy &&data) { return EmplaceEdge(fromNode, toNode, std::forward(data)); } //¹¹Ôì±ß template EdgeIter EmplaceEdge(NodeIter fromNode, NodeIter toNode, Tys &&...args) { vecNode[fromNode.idxNode].vecEdge.emplace_back( toNode.idxNode, std::forward(args)...); return EdgeIter(this, fromNode.idxNode, vecNode[fromNode.idxNode].vecEdge.size()-1); } //Ìí¼ÓË«Ïò±ß template typename std::enable_if::value, std::pair >::type AddDoublyEdge(NodeIter fromNode, NodeIter toNode, TyEdgeDataMy &&dataGo, TyEdgeDataMy &&dataRev) { auto it = AddAdge(fromNode, toNode, std::forward(dataGo)); return std::make_pair(it, AddAdge(toNode, fromNode, std::forward(dataRev))); } private: //¹¹ÔìË«Ïò±ß¸¨Öúº¯Êý template std::pair EmplaceDoublyEdgeAssist(NodeIter fromNode, NodeIter toNode, TyTupGo &&tupGo, TyTupRev &&tupRev, IndexSequence, IndexSequence) { static auto funcGo = std::mem_fn(&AddonlyGraph::EmplaceEdge< typename TypeAttachAttribute::type>::type>::type...>); static auto funcRev = std::mem_fn(&AddonlyGraph::EmplaceEdge< typename TypeAttachAttribute::type>::type>::type...>); auto itGo = TupleInvoke(funcGo, std::tuple_cat(std::forward_as_tuple(this, fromNode, toNode), std::forward(tupGo))); auto itRev = TupleInvoke(funcRev, std::tuple_cat(std::forward_as_tuple(this, toNode, fromNode), std::forward(tupRev))); return std::make_pair(itGo, itRev); } public: //¹¹ÔìË«Ïò±ß£¬ÔÚtupleÀïÃæ·Å¹¹Ôì²ÎÊý template std::pair EmplaceDoublyEdge(NodeIter fromNode, NodeIter toNode, TyTupGo &&tupGo, TyTupRev &&tupRev) { return EmplaceDoublyEdgeAssist(fromNode, toNode, std::forward(tupGo), std::forward(tupRev), MakeIndexSequence::type>::value>(), MakeIndexSequence::type>::value>()); } //Çå³ýͼ void Clear() { vecNode.clear(); } //µü´ú½Úµã NodeIter NodeBegin() { return NodeIter(this, 0); } NodeConstIter NodeBegin() const { return NodeConstIter(this, 0); } NodeIter begin() { return NodeBegin(); } NodeConstIter begin() const { return NodeBegin(); } NodeConstIter NodeConstBegin() { return NodeBegin(); } NodeIter NodeEnd() { return NodeIter(this, vecNode.size()); } NodeConstIter NodeEnd() const { return NodeConstIter(this, vecNode.size()); } NodeIter end() { return NodeEnd(); } NodeConstIter end() const { return NodeEnd(); } NodeConstIter NodeConstEnd() { return NodeEnd(); } //½ÚµãÊý size_t NodeSize() const { return vecNode.size(); } }; //µãµü´úÆ÷Ä£°å¸¨ÖúÀà template template class AddonlyGraph::TemplateNodeIterAssist: public std::iterator { protected://³ÉÔ±Êý¾Ý GraphTypeMy *pGraph;//ͼָÕë size_t idxNode;//½Úµã public://»ù±¾º¯Êý //ĬÈϹ¹Ôì TemplateNodeIterAssist(): pGraph(nullptr), idxNode(0) { } //¹¹Ô캯Êý£¬ÔÊÐíÍⲿ½øÐй¹Ôì explicit TemplateNodeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode): pGraph(o_graph), idxNode(o_idxNode) { } public://ÔËËã·ûÖØÔØ //½âÒýÓòÙ×÷ TyNodeDataMy &operator *() const { return pGraph->vecNode[idxNode].hold; } TyNodeDataMy *operator ->() const { return &operator *(); } }; //µãµü´úÆ÷Ä£°å¸¨ÖúÀàÌØ»¯ template template class AddonlyGraph::TemplateNodeIterAssist< GraphTypeMy, TyNodeDataMy, void >: public std::iterator { protected://³ÉÔ±Êý¾Ý GraphTypeMy *pGraph;//ͼָÕë size_t idxNode;//½Úµã public://»ù±¾º¯Êý //ĬÈϹ¹Ôì TemplateNodeIterAssist(): pGraph(nullptr), idxNode(0) { } //¹¹Ô캯Êý£¬ÔÊÐíÍⲿ½øÐй¹Ôì explicit TemplateNodeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode): pGraph(o_graph), idxNode(o_idxNode) { } }; //½Úµãµü´úÆ÷Ä£°åÀà template template class AddonlyGraph::TemplateNodeIter: public TemplateNodeIterAssist { public://ÓÑÔª friend AddonlyGraph; friend NodeIter; friend NodeConstIter; friend EdgeIter; friend EdgeConstIter; private://¸¨ÖúÀàÐÍ //¶ÔÓ¦µÄ±ßµü´úÆ÷ using EdgeIterMy = TemplateEdgeIter; public://»ù±¾º¯Êý //ĬÈϹ¹Ôì TemplateNodeIter() = default; //¼Ì³Ð¸¨ÖúÀàµÄ¹¹Ô캯Êý using TemplateNodeIterAssist::TemplateNodeIterAssist; //Óɷdz£À๹Ôì³£Àà TemplateNodeIter(const NodeIter &other) { operator =(other); } TemplateNodeIter &operator =(const NodeIter &other) { if((void *)this!=(void *)&other) { this->pGraph = other.pGraph; this->idxNode = other.idxNode; } return *this; } public://ÔËËã·ûÖØÔØ //µÝÔöµÝ¼õ²Ù×÷ TemplateNodeIter &operator ++() { ++ this->idxNode; return *this; } TemplateNodeIter operator ++(int) { TemplateNodeIter ret(*this); operator ++(); return ret; } TemplateNodeIter &operator --() { -- this->idxNode; return *this; } TemplateNodeIter operator --(int) { TemplateNodeIter ret(*this); operator --(); return ret; } //±È½Ï²Ù×÷ template bool operator ==(const TemplateNodeIter< GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const { return this->idxNode==other.idxNode; } template bool operator !=(const TemplateNodeIter< GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const { return !operator ==(other); } public://³ÉÔ±º¯Êý //³ö±ßµü´ú²Ù×÷ EdgeIterMy EdgeBegin() const { return EdgeIterMy(this->pGraph, this->idxNode, 0); } EdgeIterMy begin() const { return EdgeBegin(); } EdgeConstIter EdgeConstBegin() const { return EdgeBegin(); } EdgeIterMy EdgeEnd() const { return EdgeIterMy(this->pGraph, this->idxNode, this->pGraph->vecNode[this->idxNode].vecEdge.size()); } EdgeIterMy end() const { return EdgeEnd(); } EdgeConstIter EdgeConstEnd() const { return EdgeEnd(); } //´¦±ßÊý size_t EdgeSize() const { return this->pGraph->vecNode[this->idxNode].size(); } //¸Ä±äÖ¸Ïò²Ù×÷ void ChangePointer(GraphTypeMy *o_graph) { this->pGraph = o_graph; } }; //±ß´úÆ÷Ä£°å¸¨ÖúÀà template template class AddonlyGraph::TemplateEdgeIterAssist: public std::iterator { protected://³ÉÔ±Êý¾Ý GraphTypeMy *pGraph;//ͼָÕë size_t idxNode;//½ÚµãÐòºÅ size_t idxEdge;//±ßÐòºÅ public://»ù±¾º¯Êý //ĬÈϹ¹Ôì TemplateEdgeIterAssist(): pGraph(nullptr), idxNode(0), idxEdge(0) { } protected: //¹¹Ô캯Êý£¬²»ÔÊÐíÍⲿ½øÐй¹Ôì explicit TemplateEdgeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode, size_t o_idxEdge): pGraph(o_graph), idxNode(o_idxNode), idxEdge(o_idxEdge) { } public://ÔËËã·ûÖØÔØ //½âÒýÓòÙ×÷ TyEdgeDataMy &operator *() const { return pGraph->vecNode[idxNode].vecEdge[idxEdge].hold; } TyEdgeDataMy *operator ->() const { return &operator *(); } }; //±ßµü´úÆ÷Ä£°å¸¨ÖúÀàÌØ»¯ template template class AddonlyGraph::TemplateEdgeIterAssist< GraphTypeMy, TyEdgeDataMy, void >: public std::iterator { protected://³ÉÔ±Êý¾Ý GraphTypeMy *pGraph;//ͼָÕë size_t idxNode;//½ÚµãÐòºÅ size_t idxEdge;//±ßÐòºÅ public://»ù±¾º¯Êý //ĬÈϹ¹Ôì TemplateEdgeIterAssist(): pGraph(nullptr), idxNode(0), idxEdge(0) { } protected: //¹¹Ô캯Êý£¬²»ÔÊÐíÍⲿ½øÐй¹Ôì explicit TemplateEdgeIterAssist(GraphTypeMy *o_graph, size_t o_idxNode, size_t o_idxEdge): pGraph(o_graph), idxNode(o_idxNode), idxEdge(o_idxEdge) { } }; //±ßµü´úÆ÷Ä£°åÀà template template class AddonlyGraph::TemplateEdgeIter: public TemplateEdgeIterAssist { public://ÓÑÔª friend AddonlyGraph; friend NodeIter; friend NodeConstIter; friend EdgeIter; friend EdgeConstIter; private://¸¨ÖúÀàÐÍ //¶ÔÓ¦µÄ½Úµãµü´úÆ÷ using NodeIterMy = TemplateNodeIter; public://»ù±¾º¯Êý //¼Ì³Ð¸¨ÖúÀàµÄ¹¹Ô캯Êý using TemplateEdgeIterAssist::TemplateEdgeIterAssist; //Óɷdz£À๹Ôì³£Àà TemplateEdgeIter(const EdgeIter &other) { operator =(other); } TemplateEdgeIter &operator =(const EdgeIter &other) { if((void *)this!=(void *)&other) { this->pGraph = other.pGraph; this->idxNode = other.idxNode; this->idxEdge = other.idxEdge; } return *this; } public://ÔËËã·ûÖØÔØ //µÝÔöµÝ¼õÔì×÷ TemplateEdgeIter &operator ++() { ++ this->idxEdge; return *this; } TemplateEdgeIter operator ++(int) { TemplateEdgeIter ret(*this); operator ++(); return ret; } TemplateEdgeIter &operator --() { -- this->idxEdge; return *this; } TemplateEdgeIter operator --(int) { TemplateEdgeIter ret(*this); operator --(); return ret; } //±È½Ï²Ù×÷ template bool operator ==(const TemplateEdgeIter< GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const { return this->idxNode==other.idxNode && this->idxEdge==other.idxEdge; } template bool operator !=(const TemplateEdgeIter< GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const { return !operator ==(other); } public://³ÉÔ±º¯Êý //»ñÈ¡Á¬½Ó½Úµã NodeIterMy NodeFrom() const { return NodeIterMy(this->pGraph, this->idxNode); } NodeConstIter NodeConstFrom() const { return NodeFrom(); } NodeIterMy NodeTo() const { return NodeIterMy(this->pGraph, this->pGraph->vecNode[this->idxNode].vecEdge[this->idxEdge].index); } NodeIterMy NodeConstTo() const { return NodeTo(); } }; /*ͼ·ÖÀàÉèÏë 1£¬Ö»ÄÜÌí¼ÓµÄͼ£º AddNode AddEdge Clear NodeBegin NodeEnd NodeIter::EdgeBegin NodeIter::EdgeEnd NodeIter::operator ++ NodeIter::operator -- NodeIter::operator * EdgeIter::NodeFrom EdgeIter::NodeTo EdgeIter::operator ++ NodeIter::operator -- EdgeIter::operator * 2£¬Ö»ÄÜÌí¼ÓµÄͼ£¬¿ÉÒԲ鿴À´Ô´±ß£º È«²¿1º¯Êý NodeIter::EdgeFromBegin NodeIter::EdgeFromEnd 3£¬Ö»ÄÜÌí¼ÓµÄͼ£¬¿ÉÒÔ¸ù¾ÝÁ½¸ö¶¥µãÕÒÀ´Ô´ È«²¿1º¯Êý GetEdge 4£¬Ö»ÄÜÌí¼ÓµÄͼ£¬´øÓÐÁ½ÕßÊôÐÔ È«²¿2£¬3º¯Êý 5£¬¿ÉÒÔÐ޸ĵÄͼ È«²¿1º¯Êý È«²¿2º¯Êý DelNode DelEdge 6£¬ÔÚ5»ù´¡ÉÏÔö¼Ó 3¹¦ÄÜ£¬»¹Ã»ÏëºÃ */ //µ¥´¿Ðνá¹û״̬ enum class SimplexStatus { result, infeasible, unbounded,//Óнá¹û£¬Î޽⣬ÎÞ½ç }; //µ¥´¿Ðθ¨ÖúÐýת template inline void _SimplexAssistPivot(std::vector> &aMatrix, std::vector &bVector, std::vector &cVector, Ty &vValue, std::vector &bSet, std::vector &nSet, int lIndex, int eIndex) { int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý //ת»»»»³ö±äÁ¿ËùÔÚÐÐÒ»ÐÐ aMatrix[lIndex][eIndex] = 1/aMatrix[lIndex][eIndex]; bVector[lIndex] *= aMatrix[lIndex][eIndex]; for(int j=0; j inline SimplexStatus _SimplexAssistLoop(std::vector> &aMatrix, std::vector &bVector, std::vector &cVector, Ty &vValue, std::vector &bSet, std::vector &nSet, int ulp) { int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý //µ¥´¿ÐÎÑ­»· while(true) { //ÕÒ»»Èë»»³ö±äÁ¿Ñ­»· bool bFirst = true; int lIndex, eIndex; while(true) { //ÕÒ»»Èë±äÁ¿ eIndex = -1; Ty maxC = -std::numeric_limits::infinity(); for(int j=0; jmaxC) { eIndex = j; maxC = cVector[j]; } } else { //ÍË»¯Ê±Ñ¡±êºÅ×îС if(FloatGT(cVector[j], 0.0, true, ulp) && (eIndex==-1 || nSet[j]::infinity(); for(int i=0; i::infinity(); return SimplexStatus::unbounded; } //ÍË»¯Ôò¼ÌÐøÑ­»· if(bFirst && FloatEQ(minB, 0.0, true, ulp)) bFirst = false; else break; } //Ðýת _SimplexAssistPivot(aMatrix, bVector, cVector, vValue, bSet, nSet, lIndex, eIndex); } } //µ¥´¿Ðθ¨Öú³õʼ»¯ template inline SimplexStatus _SimplexAssistInit(std::vector> &aMatrix, std::vector &bVector, std::vector &cVector, Ty &vValue, std::vector &bSet, std::vector &nSet, int ulp) { int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý //Åжϻù±¾½â¿ÉÐÐÐÔ bool bPoss = true; bSet.reserve(mNum); nSet.reserve(nNum+1); for(int j=0; j::infinity(); int lIndex = -1; for(int i=0; i cVector2(nNum+1, 0); cVector2[nNum] = -1; for(int i=0; i inline typename std::enable_if::value, std::tuple, std::vector, std::vector> >::type SimplexAlgo(std::vector> &aMatrix, std::vector &bVector, std::vector &cVector, Ty &vValue, int ulp= 2000) { int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý std::vector bSet, nSet;//»ù±¾¡¢·Ç»ù±¾±äÁ¿Ë÷Òýϱê std::vector resVector;//½âϵÊýÏòÁ¿ //ÕÒ³õʼ½â SimplexStatus status = _SimplexAssistInit(aMatrix, bVector, cVector, vValue, bSet, nSet, ulp); if(status==SimplexStatus::infeasible) return make_tuple(status, resVector, bSet, nSet); //µ¥´¿ÐÎÑ­»· status = _SimplexAssistLoop(aMatrix, bVector, cVector, vValue, bSet, nSet, ulp); if(status==SimplexStatus::unbounded) return make_tuple(status, resVector, bSet, nSet); //Éú³É½âÏòÁ¿ resVector.resize(nNum, 0); for(int i=0; i