diff --git a/IoOperator.h b/IoOperator.h new file mode 100644 index 0000000..e7e9fe6 --- /dev/null +++ b/IoOperator.h @@ -0,0 +1,1606 @@ +#pragma once + +//IO²Ù×÷¿â +//20191212-1034X + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +//¿â¹ØÁªÐèÇóÎļþ +#include "TypeExtend.h" + + + + +//°´¸ñʽ¶ÁȡһÐв¢·µ»Ø×Ö·û´® +inline bool _LineStringToInit(const std::string &strIn, std::string &strField, + std::string &strValue) +{ + //Èô"(\t1)abc(\t2)(\t3)def(\t4)(\t5)ghi\r\n" + //ÕÒÓÐЧ×Ö·ûÍ· + auto itSt = std::find_if_not(strIn.begin(), strIn.end(), IsBlankChar);//a + //ÅжϿջò×¢ÊÍ'#'';'"//" + if(itSt==strIn.end() || *itSt=='#' || *itSt==';' + ||(*itSt=='/' && itSt+1!=strIn.end() && itSt[1]=='/')) + return false; + //ÕÒ×Ö¶Î⣬²»ÒªÇóºóÐø + auto itGap = std::find_if(itSt+1, strIn.end(), IsBlankChar);//\t2 + strField.assign(itSt, itGap); + //ÕÒºóÐø´Ê + auto itWordSt = std::find_if_not(itGap, strIn.end(), IsBlankChar);//d + auto ritWordEd = std::find_if_not(strIn.rbegin(), + std::string::const_reverse_iterator(itWordSt), IsBlankChar);//i + //´æ´¢Öµ£¬¿ÉÄÜΪ¿Õ + if(itWordSt!=strIn.end() && itWordSt +inline Ty2 StreamReadPredefInit(std::istream &is, Ty1 &table, + Ty2 itFieldSt, Ty2 itFieldEd, bool bReplace= true, bool bCheckNull= true) +{ + //½«¹Ø¼ü×Ö¶ÎдÈë + Ty2 itField; + std::set bstField; + for(itField=itFieldSt; itField!=itFieldEd; ++itField) { + bstField.emplace(*itField); + } + //´ÓÁ÷¶ÁÈ¡¹Ø¼ü×Ö¶Î + std::string strIn, strField, strValue; + while(std::getline(is, strIn)) { + //½âÎöÐдæÈë¶ÔÓ¦×Ö·û´® + if(!_LineStringToInit(strIn, strField, strValue)) + continue; + //ÅжÏÔÚ±íÖÐ + if(bstField.find(strField)==bstField.end()) + continue; + //ÅжÏֵΪ¿Õ + if(bCheckNull && strValue.empty()) + continue; + //Ìæ»»Ä£Ê½Ï + if(bReplace) { + auto itRes = table.find(strField); + if(itRes==table.end()) + table.emplace(std::move(strField), std::move(strValue)); + else + itRes->second = std::move(strValue); + } + //ÎÞ¶¯×÷ģʽÏ + else { + table.emplace(std::move(strField), std::move(strValue)); + } + } + //ÅжÏÌî³äÍê±Ï + for(itField=itFieldSt; itField!=itFieldEd; ++itField) { + std::string strTmp = *itField; + auto res = table.find(strTmp); + //ÈôûÕÒµ½×ֶλò¼ì²é¿ÕÇÒ×Ö¶Î¿Õ + if(res==table.end()) + break; + } + return itField; +} + + +//ÊäÈëÁ÷¶ÁÈ¡ÅäÖÃÎļþ£¬ÎÞÔ¤¶¨Òå×ֶη¶Î§£¬¶ÁÈ¡ËùÓÐÎļþµÄÖµ£¬·µ»Ø¶ÁÈ¡¸öÊý +//ÅäÖÃÎļþ¸ñʽӦΪȥµô"#define"µÄºê¶¨Òå¸ñʽ£¬'#'';'"//"¶¼Îª×¢ÊÍ +//bReplaceÊÇ·ñͬһ×ֶκóÕßÌæ»»Ç°Õߣ¬ÈôÎªÖØ¸´¼¯ºÏÇÒΪ·ñÔòÖØ¸´Ìí¼Ó +//bCheckNullÊÇ·ñ¾Ü¾ø¶ÁȡֵΪ¿ÕµÄÇé¿ö +template +inline int StreamReadAllInit(std::istream &is, Ty1 &table, + bool bReplace= true, bool bCheckNull= true) +{ + //´ÓÁ÷¶ÁÈ¡¹Ø¼ü×Ö¶Î + std::string strIn, strField, strValue; + while(std::getline(is, strIn)) { + //½âÎöÐдæÈë¶ÔÓ¦×Ö·û´® + if(!_LineStringToInit(strIn, strField, strValue)) + continue; + //ÅжÏֵΪ¿Õ + if(bCheckNull && strValue.empty()) + continue; + //Ìæ»»Ä£Ê½Ï + if(bReplace) { + auto itRes = table.find(strField); + if(itRes==table.end()) + table.emplace(std::move(strField), std::move(strValue)); + else + itRes->second = std::move(strValue); + } + //ÎÞ¶¯×÷ģʽÏ + else { + table.emplace(std::move(strField), std::move(strValue)); + } + } + return (int)table.size(); +} + + + +//ÊäÈëÁ÷¸¨Öúº¯Êý +//ʹÓÃflushË¢ÐÂÒ»ÐУ¬Ê¹ÓÃendsÇå¿Õ״̬£¬Ê¹ÓÃendlͬʱÍê³ÉˢкÍÇå¿Õ +inline bool operator >>(std::istream &is, + std::basic_ostream &(*func)(std::basic_ostream &)) +{ + bool res = (bool)is; + if(func==&std::flush>) + is.ignore(std::numeric_limits::max(), '\n'); + else if(func==&std::ends>) + is.clear(); + else if(func==&std::endl>) { + is.clear(); + is.ignore(std::numeric_limits::max(), '\n'); + } + else + assert(false); + return res; +} + + +////»ñÈ¡ÍêÕûÐÐ×÷Ϊ×Ö·û´®ÊäÈëÁ÷£¬Èç¹û»ñÈ¡ÍêisΪfailÔòÖ÷µ»ØÁ÷Ϊfail +//inline std::istringstream GetLineAsStream(std::istream &is, char gap= '\n') +//{ +// std::string strTmp; +// std::istringstream iss; +// if(!std::getline(is, strTmp, gap)) +// iss.setstate(std::ios_base::failbit); +// else +// iss.str(std::move(strTmp)); +// return std::move(iss); +//} + + + +//Êä³öÁ÷±£³ÖÀà +//ÓÃÓÚÔÚÊä³öºó¸½¼Ó¿ØÖƸñʽ£¬¶þ´ÎÊä³öÊ±ÕæÕýÊä³ö£¬ÐèÍâ²¿ÖØÔØÔËËã·û +template +class OstreamHold +{ + OstreamHold() + = delete; +}; +//Êä³öÁ÷±£³ÖÀà×óÖµÒýÓÃÌØ»¯ +template +class OstreamHold +{ +private: + std::ostream &os;//´æ´¢os + Ty &ref;//´æ´¢ÒýÓà +public: + //¹¹Ô캯Êý + explicit OstreamHold(std::ostream &o_os, Ty &o_ref): + os(o_os), ref(o_ref) + { + } + //ɾ³ý¿½±´ + OstreamHold(const OstreamHold &) + = delete; + OstreamHold &operator =(const OstreamHold &) + = delete; + //ĬÈÏÒÆ¶¯ + OstreamHold(OstreamHold &&) + = default; + OstreamHold &operator =(OstreamHold &&) + = default; + //Á÷ÒýÓà + std::ostream &operator()() const + { + return os; + } + //ÒýÓúͳÉÔ±ÒýÓà + Ty &operator *() const + { + return ref; + } + Ty *operator ->() const + { + return &ref; + } + //ת»»³£ÀàÐͰ汾 + operator OstreamHold() const + { + return OstreamHold(os, ref); + } +}; +//Êä³öÁ÷±£³ÖÀàÓÒÖµÒýÓÃÌØ»¯ +template +class OstreamHold +{ +private: + std::ostream &os;//´æ´¢os + Ty data;//´æ´¢ÒýÓà +public: + //¹¹Ô캯Êý + explicit OstreamHold(std::ostream &o_os, Ty &&o_data): + os(o_os), data(std::move(o_data)) + { + } + //ɾ³ý¿½±´ + OstreamHold(const OstreamHold &) + = delete; + OstreamHold &operator =(const OstreamHold &) + = delete; + //ĬÈÏÒÆ¶¯ + OstreamHold(OstreamHold &&) + = default; + OstreamHold &operator =(OstreamHold &&) + = default; + //ת»»×óÖµÁ÷ + OstreamHold operator()() const + { + return OstreamHold(os, data); + } + OstreamHold operator()() + { + return OstreamHold(os, data); + } + //ÒýÓúͳÉÔ±ÒýÓà + Ty &operator *() const + { + return data; + } + Ty *operator ->() const + { + return &data; + } +}; + + + +//Êä³öÁ÷¼¯ºÏÎÞËø±êÖ¾£¬×÷ΪÁ÷Êä³ö±íʾÎÞËø +class OstreamSetNoLock +{ +}; + +//Êä³öÁ÷¼¯ºÏÀà +//ÓÃÓÚ¶à¸öÊä³öÁ÷ͬʱÊä³ö£¬Ö§³Ö·ÇÁ÷ÒýÓ÷µ»ØÖµµÄ´«µÝÁ÷²Ù×÷ +//¸½¼Ó»¥³âËø¹¦Äܽӿڣ¬ÒªÇó²ÎÊý¿ÉËøÀàÐÍ£¬Í¬Ê±´ËÀàÒ²Âú×ã¿ÉËø +//ÈôÓÐËøÔòÁ÷²Ù×÷×Ô¶¯£¬³ý·Ç´«µÝ·ÇËø±êÖ¾£¬ÔÚÒ»´®Á÷²Ù×÷¿ªÊ¼½áÊøÊ±½øÐÐËø¶¨½âËø +template +class OstreamSet +{ +public: + //Êä³ö¼¯ºÏ´«µÝÀàÐÍ + template + class Hold; + +public: + std::vector vecPOs;//Êä³öÁ÷£¬¸ü¸Ä·ÇḬ̈߳²È« + std::vector vecPMtx;//Ëø£¬¸ü¸Ä·ÇḬ̈߳²È« + +public: + //ĬÈϹ¹Ôì + OstreamSet() + = default; + //ɾ³ý¿½±´ + OstreamSet(const OstreamSet &) + = delete; + OstreamSet &operator =(const OstreamSet &) + = delete; + //ĬÈÏÒÆ¶¯£¬·ÇḬ̈߳²È« + OstreamSet(OstreamSet &&) + = default; + OstreamSet &operator =(OstreamSet &&) + = default; + //ÁÐ±í¹¹Ôì + explicit OstreamSet(std::initializer_list intlOs, + std::initializer_list intlMtx = {} + ): vecPOs(intlOs), vecPMtx(intlMtx) + { + } + //µü´úÆ÷¹¹Ôì + template + explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd, + TyItMtx itMtxSt, TyItMtx itMtxEd) + { + for(; itOsSt!=itOsEd; ++itOsSt) + vecPOs.push_back(&*itOsSt); + for(; itMtxSt!=itMtxEd; ++itMtxSt) + vecPMtx.push_back(&*itMtxSt); + } + template + explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd): + OstreamSet(itOsSt, itOsEd, (TyMtx *)nullptr, (TyMtx *)nullptr) + { + } +public: + //ת·¢Á÷²Ù×÷£¬Ḭ̈߳²È«£¬°´Ë³Ðòµ÷ÓÃËø£¬Ðè±£Ö¤²»ËÀËø + template + auto operator <<(Ty &&arg) const-> + Hold(arg))> + { + //Á÷½á¹ûÀàÐÍÊý×é + using TyRes = decltype(*vecPOs.front()<(arg)); + std::vector> vecRes; + vecRes.reserve(vecPOs.size()); + //µ÷ÓÃËø¶¨ + Lock(); + //Êä³ö²¢´æ´¢ + for(auto pOs : vecPOs) { + vecRes.emplace_back(*pOs <(arg)); + } + //Éú³É½á¹ûµÄHoldÀàÐÍ + return Hold(std::move(vecRes), vecPMtx.empty()? nullptr:this); + } + //¶Ô²Ù×÷·û½øÐÐת·¢ + template + auto operator <<(std::ios_base &(*func)(std::ios_base &)) const-> + decltype(this->operator << (func)) + { + return operator << (func); + } + template + auto operator <<(std::basic_ios &(*func)(std::basic_ios &)) const-> + decltype(this->operator << (func)) + { + return operator << (func); + } + template + auto operator <<( + std::basic_ostream &(*func)(std::basic_ostream &)) const-> + decltype(this->operator << (func)) + { + return operator << (func); + } + //¶Ô²»Ëø±êÖ¾½øÐÐÁ÷²Ù×÷£¬Á÷Êä³ö½«²»½øÐÐËø¶¨ºÍ½âËø + Hold operator <<(OstreamSetNoLock) const + { + //Á÷½á¹ûÀàÐÍÊý×é + using TyRes = std::ostream &; + std::vector> vecRes; + vecRes.reserve(vecPOs.size()); + //´æ´¢ÀàÐÍ + for(auto pOs : vecPOs) { + vecRes.emplace_back(*pOs); + } + //Éú³É½á¹ûµÄHoldÀàÐÍ + return Hold(std::move(vecRes), nullptr); + } + //µ÷ÓÃostreamµÄ³ÉÔ±º¯Êý£¬½øÐÐËø¶¨£¬ºöÂÔ·µ»ØÖµ + template + void operator()(const Ty &pmf, Tys &&...args) const + { + //µ÷ÓÃËø¶¨ + Lock(); + //µ÷ÓóÉÔ±º¯Êý + for(auto pOs : vecPOs) { + (pOs->*pmf)(std::forward(args)...); + } + //µ÷ÓýâËø + Unlock(); + } + //µ÷ÓÃËø¶¨ + void Lock() const + { + //˳Ðòµ÷ÓÃËø + for(auto pMtx : vecPMtx) + pMtx->lock(); + } + void lock() const + { + Lock(); + } + //µ÷ÓýâËø + void Unlock() const + { + //·´Ðò½âËø + for(auto rit =vecPMtx.rbegin(); rit!=vecPMtx.rend(); ++rit) + (*rit)->unlock(); + } + void unlock() const + { + Unlock(); + } + //³¢ÊÔËø¶¨ + bool TryLock() const + { + //˳Ðòµ÷Óó¢ÊÔËø + unsigned i; + for(i =0; itry_lock()) + break; + } + //³¢ÊÔʧ°ÜÔò½âËø + if(i!=vecPMtx.size()) { + for(--i; i>=0; --i) + vecPMtx[i]->unlock(); + return false; + } + else + return true; + } + bool try_lock() const + { + return TryLock(); + } +}; + +//Êä³öÁ÷¼¯ºÏ´«µÝÀàÐÍ +template +template +class OstreamSet::Hold +{ + friend class OstreamSet; +private: + std::vector> vecRes;//Êä³öÁ÷µÄ½á¹ûÊý×é + const OstreamSet *pSet;//Êä³öÁ÷¼¯ºÏÖ¸Õ룬Îö¹¹½âËø±êÖ¾ + +private: + //¹¹Ô죬Êä³ö¼¯ºÏÒýÓóõʼ»¯ + explicit Hold(std::vector> &&o_vecRes, + const OstreamSet *o_pSet + ): vecRes(std::move(o_vecRes)), pSet(o_pSet) + { + } + //ɾ³ý¿½±´ + Hold(const Hold &) + = delete; + Hold &operator =(const Hold &) + = delete; + //ÒÆ¶¯²Ù×÷£¬ÒƳöÊý¾Ý²»ÐèÎö¹¹½âËø±êÖ¾ + Hold(Hold &&other) noexcept + { + this->operator =(std::move(other)); + } + Hold &operator =(Hold &&other) noexcept + { + if(this!=&other) { + vecRes = std::move(other.vecRes); + pSet = std::move(other.pSet); + other.pSet = nullptr; + } + return *this; + } +public: + //Îö¹¹º¯Êý£¬¸ù¾Ý±êÖ¾½øÐнâËø£¬·´Ðò½âËø + ~Hold() + { + if(pSet!=nullptr) { + //µ÷ÓýâËø + pSet->Unlock(); + } + } +public: + //ת·¢Á÷²Ù×÷£¬×ª·¢ºóÈ¥³ý½âËø±êÖ¾ + template + auto operator <<(Ty &&arg)-> + Hold(arg))> + { + //´Ë¶ÔÏó²»ÐèÎö¹¹½âËø + auto ptr = pSet; + pSet = nullptr; + //еÄÁ÷²Ù×÷½á¹ûÀàÐÍ + using TyResTmp = decltype(vecRes.front().hold<(arg)); + std::vector> vecResTmp; + vecResTmp.reserve(vecRes.size()); + //Á÷Êä³ö²¢´æ´¢ + for(auto &refRes : vecRes) { + vecResTmp.emplace_back(refRes.hold <(arg)); + } + //¹¹ÔìеÄHoldÀàÐÍ£¬×ªÒåÎö¹¹½âËø±êÖ¾ + return Hold(std::move(vecResTmp), ptr); + } + //¶Ô²Ù×÷·û½øÐÐת·¢ + template + auto operator <<(std::ios_base &(*func)(std::ios_base &))-> + decltype(this->operator << (func)) + { + return operator << (func); + } + template + auto operator <<(std::basic_ios &(*func)(std::basic_ios &))-> + decltype(this->operator << (func)) + { + return operator << (func); + } + template + auto operator <<( + std::basic_ostream &(*func)(std::basic_ostream &))-> + decltype(this->operator << (func)) + { + return operator << (func); + } +}; + + + +//¶ÏÑÔ²Ù×÷ÀàÊä³öÑ¡Ïî +enum class AssertOption +{ + thrw_log,//Å׳öÒì³£²¢Êä³öÈÕÖ¾ + thrw,//Å׳öÒì³£ + asst_log,//µ÷ÊÔ¶ÏÑÔ²¢Êä³öÈÕÖ¾ + asst,//µ÷ÊÔ¶ÏÑÔ + log,//Êä³öÈÕÖ¾ + none,//ÎÞ²Ù×÷ +}; + +//¶ÏÑÔ²Ù×÷Àà +template +class AssertOperator +{ +private: + //·Ç²¶»ñÒì³£ + class NoCatchError: + private std::runtime_error + { + //¼Ì³Ð»ùÀ๹Ô캯Êý£¨³ýĬÈÏ¿½±´¹¹Ô죩 + using std::runtime_error::runtime_error; + public: + //ĬÈϹ¹Ôì + NoCatchError(): + std::runtime_error("") + { + } + //ʹÓü̳Ðwhat + using std::runtime_error::what; + //Ê¡ÂԺϳÉ5¿½±´ + }; + +private: + TyOs &os;//Êä³öÀà +public: + AssertOption option;//Êä³öÑ¡Ïî + +public: + //¹¹Ôì + AssertOperator() = + delete; + explicit AssertOperator(TyOs &o_os, AssertOption o_option): + os(o_os), option(o_option) + { + } +public: + //Ö¸¶¨Ñ¡Ïî½øÐжÏÑÔ + bool operator()(AssertOption optionTmp, + bool bCond, const std::string &str= "") const + { + if(bCond) + return true; + //°´Ñ¡Ïî½øÐвÙ×÷ + if(optionTmp==AssertOption::thrw_log) { + os <(buf), size); + if(ofs.bad()) + throw std::runtime_error("Can't Write File"); + return *this; + } + //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template + typename std::enable_if::value, BinWriteFile & + >::Type WriteArray(const Ty *pt, size_t count) + { + WriteBuf(pt, sizeof(Ty)*count); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template + typename std::enable_if::value, BinWriteFile & + >::Type WriteArray(const Ty *pt, size_t count) + { + for(; count!=0; --count, ++pt) + *this <<*pt; + return *this; + } +public: + //¶ÔÄÚÖÃÀàÐͽøÐÐÎļþдÈ룬°üÀ¨ÄÚÖÃÀàÐÍÊý×é + template + typename std::enable_if::type>::value, BinWriteFile & + >::type operator <<(const Ty &r) + { + WriteBuf(&r, sizeof(r)); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþдÈë + template + typename std::enable_if::type>::value, BinWriteFile & + >::type operator <<(const Ty (&arrStr)[N]) + { + for(int64_t i=0; i + BinWriteFile &operator <<(const std::pair &pr) + { + *this < + BinWriteFile &operator <<(const std::tuple &tup) + { + TupleWrite(tup); + return *this; + } + template + typename std::enable_if<(index>=0), void + >::type TupleWrite(const std::tuple &tup) + { + *this <(tup); + TupleWrite(tup); + } + template + void TupleWrite(const Ty &tup) + { + } + //¶Ôstring½øÐÐÎļþдÈë + template + BinWriteFile &operator <<(const std::basic_string &str) + { + //д³ß´ç + int64_t size = str.size(); + operator <<(size); + //дÊý¾Ý + WriteBuf(&str[0], (size_t)(size*sizeof(Ty))); + return *this; + } + //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþдÈë + template + typename std::enable_if::value, BinWriteFile & + >::type operator <<(const std::vector &vec) + { + //д³ß´ç + int64_t size = vec.size(); + operator <<(size); + //дÊý¾Ý + WriteBuf(vec.data(), size*sizeof(Ty)); + return *this; + } + //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë + template + typename std::enable_if::value, BinWriteFile & + >::type operator <<(const std::vector &vec) + { + //д³ß´ç + int64_t size = vec.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : vec) + *this < + typename std::enable_if::value, BinWriteFile & + >::type operator <<(const std::array &arr) + { + //дÊý¾Ý + WriteBuf(arr.data(), c_size*sizeof(Ty)); + return *this; + } + //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë + template + typename std::enable_if::value, BinWriteFile & + >::type operator <<(const std::array &arr) + { + //дÊý¾Ý + for(auto &r : arr) + *this < + BinWriteFile &operator <<(const std::deque &deq) + { + //д³ß´ç + int64_t size = deq.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : deq) + *this < + BinWriteFile &operator <<(const std::list &lis) + { + //д³ß´ç + int64_t size = lis.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : lis) + *this < + BinWriteFile &operator <<(const std::set &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this < + BinWriteFile &operator <<(const std::multiset &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this < + BinWriteFile &operator <<(const std::map &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this < + BinWriteFile &operator <<(const std::multimap &bst) + { + //д³ß´ç + int64_t size = bst.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : bst) + *this < + BinWriteFile &operator <<(const std::unordered_set &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this < + BinWriteFile &operator <<(const std::unordered_multiset &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this < + BinWriteFile &operator <<(const std::unordered_map &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this < + BinWriteFile &operator <<(const std::unordered_multimap &htb) + { + //д³ß´ç + int64_t size = htb.size(); + operator <<(size); + //дÊý¾Ý + for(auto &r : htb) + *this < +class BinWriteFileIter: + public std::iterator +{ +private://Êý¾Ý + BinWriteFile *pBwf;//¹ØÁªÎļþ + +public://»ù±¾º¯Êý + //ûÓÐĬÈϹ¹Ôì + BinWriteFileIter() + = delete; + //¹ØÁª¹¹Ôì + BinWriteFileIter(BinWriteFile &bwf): + pBwf(&bwf) + { + } +public://ÔËËã·ûÖØÔØ + //½âÒýÓòÙ×÷£¬·µ»Ø×ÔÉí + BinWriteFileIter &operator *() const + { + return *this; + } + //µÝÔö²Ù×÷£¬Ê²Ã´Ò²²»×ö£¬·µ»Ø×ÔÉí + BinWriteFileIter &operator ++() + { + return *this; + } + BinWriteFileIter &operator ++(int) + { + return *this; + } + //¸³Öµ²Ù×÷£¬½øÐÐÊä³ö + BinWriteFileIter &operator =(const Ty &data) + { + *pBwf < +class BinReadFileIter; +//¶ÁÀàÐͶþ½øÖÆÎļþÀà +//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿ +class BinReadFile +{ +public: + std::ifstream ifs;//ÎļþÁ÷ + bool bFast = false;//¿ìËÙģʽ£¬£¬Ò»´ÎÉêÇë×ã¹»Äڴ棬Êý×é¼Ç¼´íÎó¿ÉÄÜÔì³ÉÄÚ´æ²»×㣬¿ÉÔÚÈκÎʱºò¸ü¸Ä + bool bSave = false;//½ÚԼģʽ£¬ÉêÇëÄÚ´æÊ±²»ÉêÇë¶îÍâÁ¿£¬½ö¿ìËÙģʽÓ㬿ÉÔÚÈκÎʱºò¸ü¸Ä + static constexpr int64_t bufSize = 4096;//¶ÁÈ¡»º´æ´óС + +public: + //¹¹Ôì + explicit BinReadFile(bool o_bFast= false, bool o_bSave= false): + bFast(o_bFast), bSave(o_bSave) + { + } + //´ò¿ªÎļþ¹¹Ôì + template::value>::type + > explicit BinReadFile(Ty &&name, bool o_bFast= false, bool o_bSave= false): + bFast(o_bFast), bSave(o_bSave) + { + Open(std::forward(name)); + } + //Îö¹¹ + ~BinReadFile() + = default; + //ɾ³ý¿½±´ + BinReadFile(const BinReadFile &) + = delete; + BinReadFile &operator =(BinReadFile &) + = delete; + //ÒÆ¶¯¹¹Ôì + BinReadFile(BinReadFile &&file) + = default; + //ÒÆ¶¯¸³Öµ + BinReadFile &operator =(BinReadFile &&file) + = default; + +public: + //´ò¿ªÎļþ + BinReadFile &Open(const std::string &name) + { + ifs.close(); + ifs.open(name, std::ios::binary); + if(ifs.bad()) + throw std::runtime_error("Open Read File Bad Error"); + return *this; + } + //¸²¸ÇCloseº¯Êý£¬Èô¼ì²â½áβÔò·µ»Ø¼ì²â½á¹û + bool Close(bool bTestEnd = false) + { + bool res = !bTestEnd; + //¼ì²â½áβ + if(bTestEnd) { + res = TestEof(); + } + ifs.close(); + if(ifs.bad()) + throw std::runtime_error("Can't Close File"); + return res; + } + //·µ»Ø´ò¿ª×´Ì¬ + bool IsOpen() const + { + return ifs.is_open(); + } + //ÎļþÁ÷¿ÉÓà + bool IsFail() const + { + return !ifs.good(); + } + operator bool() const + { + return ifs.good(); + } + //Çå³ý´íÎó±êÖ¾ + void Clear() + { + ifs.clear(); + } + //¼ì²â½á⣬»á½øÐÐÒ»´Î¶ÁÈ¡²Ù×÷ + bool TestEof() + { + ifs.get(); + if(ifs.bad()) + throw std::runtime_error("Read File Bad Error"); + return ifs.eof(); + } + //ÖØ¶¨Î»Î»Öà + BinReadFile &Seekg(std::ifstream::pos_type pos) + { + ifs.seekg(pos); + return *this; + } + BinReadFile &Seekg(std::ifstream::off_type off, std::ios_base::seekdir dir) + { + ifs.seekg(off, dir); + return *this; + } + //²éѯλÖà + std::ifstream::pos_type Tellg() + { + return ifs.tellg(); + } + //¶Ô»º³åÇø½øÐÐÎļþ¶ÁÈ¡ + BinReadFile &ReadBuf(void *buf, size_t size) + { + ifs.read(reinterpret_cast(buf), size); + if(ifs.bad()) + throw std::runtime_error("Read File Bad Error"); + return *this; + } + //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template + typename std::enable_if::value, BinReadFile & + >::Type ReadArray(Ty *pt, size_t count) + { + ReadBuf(pt, sizeof(Ty)*count); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡ + template + typename std::enable_if::value, BinReadFile & + >::Type ReadArray(Ty *pt, size_t count) + { + for(; count!=0; --count, ++pt) { + if(ifs.fail()) + return; + *this >>*pt; + } + return *this; + } +public: + //¶ÔÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬°üÀ¨ÄÚÖÃÀàÐÍÊý×é + template + typename std::enable_if::type>::value, BinReadFile & + >::type operator >>(Ty &r) + { + ReadBuf(&r, sizeof(r)); + return *this; + } + //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþ¶ÁÈ¡ + template + typename std::enable_if::type>::value, BinReadFile & + >::type operator >>(Ty (&arrStr)[N]) + { + for(int64_t i=0; i>arrStr[i]; + } + return *this; + } + //¶Ôpair½øÐÐÎļþ¶ÁÈ¡ + template + BinReadFile &operator >>(std::pair &pr) + { + *this >>pr.first >>pr.second; + return *this; + } + //¶Ôtuple½øÐÐÎļþ¶ÁÈ¡ + template + BinReadFile &operator >>(std::tuple &tup) + { + TupleRead(tup); + return *this; + } + template + typename std::enable_if<(index>=0), void + >::type TupleRead(std::tuple &tup) + { + *this >>std::get(tup); + TupleRead(tup); + } + template + void TupleRead(Ty &tup) + { + } + //¶Ôstring½øÐÐÎļþ¶ÁÈ¡ + template + BinReadFile &operator >>(std::basic_string &str) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + str.clear(); + //¶ÁÊý¾Ý + if(bFast) { + if(bSave) + str.reserve((typename std::basic_string::size_type)size); + str.resize((typename std::basic_string::size_type)size); + ReadBuf(&str[0], (size_t)(size*sizeof(Ty))); + } + else { + constexpr int64_t perBufSize = bufSize/sizeof(Ty); + for(; size>0; size-=perBufSize) { + if(ifs.fail()) + return *this; + int64_t realSize = size::size_type)(nowSize+realSize)); + ReadBuf(&str[0]+nowSize, (size_t)(realSize*sizeof(Ty))); + } + } + return *this; + } + //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ + template + typename std::enable_if::value, BinReadFile & + >::type operator >>(std::vector &vec) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + constexpr int64_t perBufSize = bufSize/sizeof(Ty); + vec.clear(); + //¶ÁÊý¾Ý + if(bFast) { + if(bSave) + vec.reserve((typename std::vector::size_type)size); + vec.resize((typename std::vector::size_type)size); + ReadBuf(vec.data(), size*sizeof(Ty)); + } + else { + for(; size>0; size-=perBufSize) { + if(ifs.fail()) + return *this; + int64_t realSize = size::size_type)(nowSize+realSize)); + ReadBuf(vec.data()+nowSize, realSize*sizeof(Ty)); + } + } + return *this; + } + //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý + template + typename std::enable_if::value, BinReadFile & + >::type operator >>(std::vector &vec) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + //¶ÁÊý¾Ý + vec.clear(); + if(bFast) { + if(bSave) + vec.reserve((typename std::vector::size_type)size); + vec.resize((typename std::vector::size_type)size); + for(auto &r : vec) { + if(ifs.fail()) + return *this; + *this >>r; + } + } + else { + for(int64_t i=0; i>vec.back(); + } + } + return *this; + } + //¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ + template + typename std::enable_if::value, BinReadFile & + >::type operator >>(std::array &arr) + { + //¶ÁÊý¾Ý + ReadBuf(arr.data(), c_size*sizeof(Ty)); + return *this; + } + //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡ + template + typename std::enable_if::value, BinReadFile & + >::type operator >>(std::array &arr) + { + //¶ÁÊý¾Ý + for(auto &ele: arr) { + if(ifs.fail()) + return *this; + *this >>ele; + } + return *this; + } + //¶Ôdeque½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý + template + BinReadFile &operator >>(std::deque &deq) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + deq.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i>deq.back(); + } + return *this; + } + //¶Ôlist½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý + template + BinReadFile &operator >>(std::list &lis) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + lis.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i>lis.back(); + } + return *this; + } + //¶Ô¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::set &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i>data; + bst.insert(bst.end(), std::move(data)); + } + return *this; + } + //¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::multiset &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i>data; + bst.insert(bst.end(), std::move(data)); + } + return *this; + } + //¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::map &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i>data; + if(ifs.fail()) + return *this; + auto res = bst.emplace_hint(bst.end(), std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()); + *this >>res->second; + } + return *this; + } + //¶Ô¶àÖµ¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::multimap &bst) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + bst.clear(); + //¶ÁÊý¾Ý + for(int64_t i=0; i>data; + if(ifs.fail()) + return *this; + auto res = bst.emplace_hint(bst.end(), std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()); + *this >>res->second; + } + return *this; + } + //¶Ô¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::unordered_set &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_set::size_type)size); + for(int64_t i=0; i>data; + htb.insert(std::move(data)); + } + return *this; + } + //¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::unordered_multiset &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_multiset::size_type)size); + for(int64_t i=0; i>data; + htb.insert(std::move(data)); + } + return *this; + } + //¶Ô¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::unordered_map &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_map::size_type)size); + for(int64_t i=0; i>data; + if(ifs.fail()) + return *this; + auto res = htb.emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()).first; + *this >>res->second; + } + return *this; + } + //¶Ô¶àÖµ¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ + template + BinReadFile &operator >>(std::unordered_multimap &htb) + { + //¶Á³ß´ç + int64_t size = -1; + operator >>(size); + if(ifs.fail()) + return *this; + htb.clear(); + //¶ÁÊý¾Ý + if(bFast) + htb.reserve((typename std::unordered_multimap::size_type)size); + for(int64_t i=0; i>data; + if(ifs.fail()) + return *this; + auto res = htb.emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(data)), std::make_tuple()); + *this >>res->second; + } + return *this; + } +}; + +//¶ÁÀàÐͶþ½øÖÆÎļþÀàµü´úÆ÷ +//ÊÇÊäÈëµü´úÆ÷£¬´æ´¢ÀàÐͱØÐë¿ÉĬÈϹ¹Ôì +template +class BinReadFileIter: + public std::iterator +{ +private://Êý¾Ý + BinReadFile *pBrf;//¹ØÁªÎļþ + int64_t size;//Ê£ÓàдÈë´óС£¬¸ºÊý±íʾÎÞÏÞдÈë + Ty data;//´æ´¢Êý¾Ý + +public://»ù±¾º¯Êý + //ĬÈϹ¹Ô죬³ÉΪβºóµü´úÆ÷ + BinReadFileIter(): + pBrf(nullptr), size(0) + { + } + //¹ØÁª¹¹Ô죬³õʼ½øÐжÁÈ¡£¬¿ÉÑ¡ÔñµÄ¼ÓÈë¶ÁÈ¡ÊýÁ¿ÏÞÖÆ + BinReadFileIter(BinReadFile &brf, int64_t o_size= -1): + pBrf(&brf), size(o_size) + { + Read(); + } +public://ÔËËã·ûÖØÔØ + //½âÒýÓòÙ×÷£¬·µ»ØÊý¾ÝÒýÓã¬Ö§³ÖÒÆ¶¯²Ù×÷ + Ty &operator *() const + { + return data; + } + Ty *operator ->() const + { + return &operator *(); + } + //µÝÔö²Ù×÷£¬Í¬Ê±½øÐжÁÈ¡ + BinReadFileIter &operator ++() + { + Read(); + return *this; + } + BinReadFileIter operator ++(int) + { + BinReadFileIter ret(*this); + operator ++(); + return ret; + } + //±È½Ï²Ù×÷£¬Ö¸ÏòÏàͬµÄÎļþ¾ÍÈÏΪÏàͬ + bool operator ==(const BinReadFileIter &other) const + { + return pBrf==other.pBrf; + } + bool operator !=(const BinReadFileIter &other) const + { + return !operator ==(other); + } +private: + //¶ÁÈ¡Êý¾Ý£¬Ã¿´Î¶ÁÈ¡ÊÇÎö¹¹ÔÙĬÈϹ¹ÔìÒ»´ÎÊý¾Ý£¬ÒÔÖ§³ÖÒÆ¶¯²Ù×÷ + void Read() + { + assert(pBrf!=nullptr); + //ÈôÊ£Óà0ÔòתΪβºó + if(size==0) { + pBrf = nullptr; + return; + } + //Çå³ý + CallDestruct(data); + new(&data) Ty(); + //¶ÁÈ¡ + *pBrf >>data; + //Èô¶Áȡʧ°ÜÔòתΪβºó + if(!*pBrf) + pBrf = nullptr; + //¼õÉÙÊ£Óà + if(size>0) + -- size; + } +}; diff --git a/StruAndAlgo.h b/StruAndAlgo.h new file mode 100644 index 0000000..f4d8113 --- /dev/null +++ b/StruAndAlgo.h @@ -0,0 +1,2562 @@ +#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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + + + + +//************ +//ÀàÐͱðÃûÀ©Õ¹ +//************ + + +//durationÀ©Õ¹ +namespace std +{ +namespace chrono +{ +typedef duration> days; +typedef duration> weeks; +} +} + + + +//************ +//»ù´¡ÀàÐÍÀ©Õ¹ +//************ + +//ÎÞÓÃռλÀàÐÍ +template +class BlankType +{ +}; + + + +//²âÊÔ²ÎÊýÊÇ·ñºÏ·¨Àà +template +struct ParamValidTester +{ + typedef void type; +}; + + +//ÏÈÈ¥³ýÒýÓÃÔÙÈ¥³ý³£ÊýÒ×±äÊôÐÔ +template +struct RemoveCVRef +{ + using type = typename std::remove_cv::type>::type; +}; + +//ºóÕßÈ¥³ýÒýÓó£ÊýÒ×±äºóÊÇ·ñΪǰÕß +template +struct IsRemoveCVRefSame: + std::is_same::type> +{ +}; + + +//ºóÕß²ÎÊý°üÊÇ·ñÒª²»Ã»ÓвÎÊý£¬Òª²»Ö»ÓÐÒ»¸ö²¢ÇÒΪǰÕß +template +struct IsNoneOrSame: + std::integral_constant +{ +}; +template +struct IsNoneOrSame: + std::is_same +{ +}; + +//ºóÕß²ÎÊý°üÊÇ·ñÒª²»Ã»ÓвÎÊý£¬Òª²»Ö»ÓÐÒ»¸ö²¢ÇÒÈ¥³ýÒýÓó£ÊýÒ×±äºóΪǰÕß +template +struct IsNoneOrRemoveCVRefSame: + std::integral_constant +{ +}; +template +struct IsNoneOrRemoveCVRefSame: + IsRemoveCVRefSame +{ +}; + + +//²âÊÔÊÇ·ñΪµü´úÆ÷ +template +struct IsIteratorType: + std::false_type +{ +}; +template +struct IsIteratorType::iterator_category>::type +>: std::true_type +{ +}; + + +//²âÊÔÈ¥³ý³£Ò×±äÒ×ÓÃÊôÐÔºó£¬ÊÇ·ñΪ×Ö·ûÖ¸Õ룬×Ö·ûÊý×é»òstringÀàÐÍ +template +struct IsRemoveCVRefSameSzOrString: + std::integral_constant::value + || IsRemoveCVRefSame::value + || (std::is_array::type>::value + && IsRemoveCVRefSame::type>::type>::value) + || IsRemoveCVRefSame::value> +{ +}; + + + +//Éú³Éµü´úÆ÷½âÒýÓõÄÀàÐÍ£¬±£Áô³£Ò×±äÒýÓÃÊôÐÔ +template +struct IteratorDerefType +{ + using type = decltype(*std::declval()); +}; + +//Éú³Éµü´úÆ÷½âÒýÓõÄÀàÐÍÔÙÈ¥³ý³£Ò×±äÒýÓÃÊôÐÔ +template +struct IteratorRemoveCVRefDerefType +{ + using type = typename RemoveCVRef::type>::type; +}; + + + +//¸ù¾ÝÌṩÀ´Ô´ÀàÐ͵ÄÒýÓᢳ£Êý¡¢Ò×±äÊôÐÔ£¬¶ÔÄ¿µÄÀàÐ͸½¼ÓͬÑùµÄÊôÐÔ +template +struct TypeAttachAttribute +{ + using type = TyDst; +}; +//³£ÊôÐÔÌØ»¯ +template +struct TypeAttachAttribute +{ + using type = typename std::add_const< + typename TypeAttachAttribute::type>::type; +}; +//Ò×±äÊôÐÔÌØ»¯ +template +struct TypeAttachAttribute +{ + using type = typename std::add_volatile< + typename TypeAttachAttribute::type>::type; +}; +//×óÖµÒýÓÃÊôÐÔÌØ»¯ +template +struct TypeAttachAttribute +{ + using type = typename std::add_lvalue_reference< + typename TypeAttachAttribute::type>::type; +}; +//ÓÒÖµÒýÓÃÊôÐÔÌØ»¯ +template +struct TypeAttachAttribute +{ + using type = typename std::add_rvalue_reference< + typename TypeAttachAttribute::type>::type; +}; + + + +//Çóµ÷Ó÷µ»ØÖµÀàÐÍ +template +struct InvokeReturnType +{ + using type = decltype(std::declval()(std::declval()...)); +}; + + + +//ÕûÊýÐòÁÐÄ£°å +template +struct IndexSequence +{ +}; +template<> +struct IndexSequence<> +{ + using value_type = size_t; + static constexpr size_t size() + { + return 0; + } +}; +template +struct IndexSequence +{ + using value_type = size_t; + static constexpr size_t size() + { + return IndexSequence::size()+1; + } +}; + +//ÕûÊýÄ£°åÌí¼ÓÔªËØº¯Êý +template +inline IndexSequence AddIndexSequence(IndexSequence) +{ + return IndexSequence(); +} + +//Éú³É˳ÐòµÝÔöÕûÊýÄ£°å¸¨ÖúÀà +template +struct _MakeIndexSequenceAssist +{ + using type = decltype(AddIndexSequence( + typename _MakeIndexSequenceAssist::type())); +}; +template<> +struct _MakeIndexSequenceAssist<0> +{ + using type = IndexSequence<>; +}; +//Éú³É˳ÐòµÝÔöÕûÊýÄ£°åÀà +template +using MakeIndexSequence = typename _MakeIndexSequenceAssist::type; + + + +//Ä£°å¶¨³¤ÕûÐÎ +template +struct TemplateInt +{ +}; +template<> +struct TemplateInt +{ + using type = int8_t; +}; +template<> +struct TemplateInt +{ + using type = uint8_t; +}; +template<> +struct TemplateInt +{ + using type = int16_t; +}; +template<> +struct TemplateInt +{ + using type = uint16_t; +}; +template<> +struct TemplateInt +{ + using type = int32_t; +}; +template<> +struct TemplateInt +{ + using type = uint32_t; +}; +template<> +struct TemplateInt +{ + using type = int64_t; +}; +template<> +struct TemplateInt +{ + using type = uint64_t; +}; + + + +//¹ãÒåµÄ±È½Ïº¯ÊýÀà +template +struct GeneralLess +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return arg1 +struct GeneralEqualTo +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return arg1==arg2; + } +}; +template +struct GeneralLessEqual +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return arg1<=arg2; + } +}; +template +struct GeneralGreater +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return arg1>arg2; + } +}; +template +struct GeneralGreaterEqual +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return arg1>=arg2; + } +}; +template +struct GeneralNotEqualTo +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return arg1!=arg2; + } +}; + + +//À©Õ¹µÄ¹ãÒå±È½Ïº¯ÊýÀ࣬ʹÓÃСÓں͵ÈÓÚ²Ù×÷ÔËËã +template +struct ExtendGeneralLessEqual +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return arg1 +struct ExtendGeneralGreater +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return !(arg1 +struct ExtendGeneralGreaterEqual +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return !(arg1 +struct ExtendGeneralNotEqualTo +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return !(arg1==arg2); + } +}; + + +//±È½ÏÀàÐ͵ĺ¯Êý·â×° +template +using CompareType = std::function; + + +//±È½ÏÀຯÊýÀ©Õ¹£¬Ê¹ÓÃСÓں͵ÈÓÚº¯Êý +template +struct ExtendLessEqualWrap +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; +public: + CompareType funcLT; + CompareType funcEQ; +public: + explicit ExtendLessEqualWrap(const CompareType &o_funcLT, + const CompareType &o_funcEQ) + : + funcLT(o_funcLT), funcEQ(o_funcEQ) + { + } + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return funcLT(arg1, arg2) || funcEQ(arg1, arg2); + } +}; +template +struct ExtendGreaterWrap +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; +public: + CompareType funcLT; + CompareType funcEQ; +public: + explicit ExtendGreaterWrap(const CompareType &o_funcLT, + const CompareType &o_funcEQ) + : + funcLT(o_funcLT), funcEQ(o_funcEQ) + { + } + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return !(funcLT(arg1, arg2) || funcEQ(arg1, arg2)); + } +}; +template +struct ExtendGreaterEqualWrap +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; +public: + CompareType funcLT; + CompareType funcEQ; +public: + explicit ExtendGreaterEqualWrap(const CompareType &o_funcLT, + const CompareType &o_funcEQ) + : + funcLT(o_funcLT), funcEQ(o_funcEQ) + { + } + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return !funcLT(arg1, arg2); + } +}; +template +struct ExtendNotEqualToWrap +{ + typedef bool result_type; + typedef Ty1 first_argument_type; + typedef Ty2 second_argument_type; +public: + CompareType funcLT; + CompareType funcEQ; +public: + explicit ExtendNotEqualToWrap(const CompareType &o_funcLT, + const CompareType &o_funcEQ) + : + funcLT(o_funcLT), funcEQ(o_funcEQ) + { + } + result_type operator()(const first_argument_type &arg1, + const second_argument_type &arg2) const + { + return !funcEQ(arg1, arg2); + } +}; + + + +//´æ´¢Ä³ÀàÐÍ£¬¿ÉÒÔΪֵ»òÒýÓ㬶Ը÷ÖÖÇé¿öÒѽøÐÐÌØ»¯ +//ÖµÀàÐÍÌØ»¯ +template +struct TypeHolder +{ + Ty hold; +public: + //¹¹Ôì + TypeHolder(const Ty &o_hold): + hold(o_hold) + { + } + TypeHolder(Ty &&o_hold): + hold(std::move(o_hold)) + { + } +}; +//×óÖµÒýÓÃÌØ»¯ +template +struct TypeHolder +{ + Ty &hold; +public: + //¹¹Ôì + TypeHolder(Ty &o_hold): + hold(o_hold) + { + } +}; +//ÓÒÖµÒýÓÃÌØ»¯ +template +struct TypeHolder +{ + Ty &&hold; +public: + //¹¹Ôì + TypeHolder(Ty &&o_hold): + hold(std::move(o_hold)) + { + } +}; + + + +//´æ´¢Ä³ÖµÀàÐÍ£¬²»ÄÜΪÒýÓã¬ÀàÐÍÖ§³Övoid +template +struct ValueHolder +{ +public: + using RefType = Ty &; + using ConstRefType = const Ty &; + using PtrType = Ty *; + using ConstPtrType = const Ty *; +public: + Ty hold; +public: + //Ä£°å¹¹Ôì + template + explicit ValueHolder(Ty_S &&...args): + hold(std::forward(args)...) + { + } +}; +//voidÌØ»¯ +template<> +struct ValueHolder +{ + using RefType = void; + using ConstRefType = void; + using PtrType = void; + using ConstPtrType = void; +}; + + + +//********************** +//ÀàÐͳÉÔ±»ò¸¨Öúº¯ÊýÀ©Õ¹ +//********************** + +//µ÷ÓñäÁ¿µÄÎö¹¹º¯Êý +template +inline void CallDestruct(Ty &value) +{ + value.~Ty(); +} + +//µ÷ÓñäÁ¿µÄ¹¹Ô캯Êý£¬ÒªÇó±äÁ¿ÒѾ­Îö¹¹ +template +inline void CallConstruct(Ty &value, Ty_S &&...arg_s) +{ + new(&value) Ty(std::forward(arg_s)...); +} + +//µ÷ÓñäÁ¿µÄÎö¹¹º¯ÊýºÍ¹¹Ô캯Êý +template +inline void CallRestruct(Ty &value, Ty_S &&...arg_s) +{ + CallDestruct(value); + CallConstruct(value, std::forward(arg_s)...); +} + + + +//ÌáÈ¡±äÁ¿µÄ×óÖµÒýÓà +template +inline Ty &GetLref(Ty &&value) +{ + return value; +} +//ÌáÈ¡±äÁ¿µÄ³£×óÖµÒýÓà +template +inline const Ty &GetConstLref(Ty &&value) +{ + return value; +} + + +//¶Ô±äÁ¿½øÐÐÖµ¿½±´ +template +inline Ty GetValueCopy(const Ty &value) +{ + return Ty(value); +} + + + +//c·ç¸ñ×Ö·û´®×ª»¯×Ö·û´®£¬×Ö·ûÖ¸ÕëÖØÔØ +inline std::string OverrideSzToStr(const char *sz) +{ + return std::string(sz); +} +inline std::string OverrideSzToStr(char *sz) +{ + return std::string(sz); +} +//c·ç¸ñ×Ö·û´®×ª»¯×Ö·û´®£¬×Ö·ûÊý×éÖØÔØ +template +inline typename std::enable_if::type>::value + && IsRemoveCVRefSame::type>::type>::value, std::string +>::type OverrideSzToStr(Ty &&sz) +{ + return std::string(std::forward(sz)); +} +//c·ç¸ñ×Ö·û´®×ª»¯×Ö·û´®£¬ÆäÓàÇé¿öÖØÔØ +template +inline Ty &&OverrideSzToStr(Ty &&arg) +{ + return std::forward(arg); +} + + + +//ÕûÐαȽϸ¨Öúºê +#define _IS_INT_TYPE(Ty1, Ty2) \ + (std::is_integral::value && std::is_integral::value) +#define _INT_SIGN_UNSIGN(Ty1, Ty2) \ + ((std::is_integral::value && std::is_signed::value)\ + && std::is_unsigned::value) + +//ÕûÐÎÀàÐͰ²È«ÅжÏСÓÚ +template +inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty1, Ty2), bool +>::type IntLT(Ty1 num1, Ty2 num2) +{ + return (num1<0) ? (true) + : (static_cast::type>(num1) +inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty2, Ty1), bool +>::type IntLT(Ty1 num1, Ty2 num2) +{ + return (num2<0) ? (false) + : (num1::type>(num2)); +} +template +inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2) + && !_INT_SIGN_UNSIGN(Ty1, Ty2) && !_INT_SIGN_UNSIGN(Ty2, Ty1), bool +>::type IntLT(Ty1 num1, Ty2 num2) +{ + return num1 +inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty1, Ty2), bool +>::type IntEQ(Ty1 num1, Ty2 num2) +{ + return (num1<0) ? (false) + : (static_cast::type>(num1)==num2); +} +template +inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty2, Ty1), bool +>::type IntEQ(Ty1 num1, Ty2 num2) +{ + return (num2<0) ? (false) + : (num1==static_cast::type>(num2)); +} +template +inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2) + && !_INT_SIGN_UNSIGN(Ty1, Ty2) && !_INT_SIGN_UNSIGN(Ty2, Ty1), bool +>::type IntEQ(Ty1 num1, Ty2 num2) +{ + return num1==num2; +} + +//ÕûÐÎÀàÐͰ²È«ÅжÏСÓÚµÈÓÚ +template +inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool +>::type IntLTE(Ty1 num1, Ty2 num2) +{ + return IntLT(num1, num2) || IntEQ(num1, num2); +} + +//ÕûÐÎÀàÐͰ²È«ÅжϴóÓÚ +template +inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool +>::type IntGT(Ty1 num1, Ty2 num2) +{ + return !(IntLT(num1, num2) || IntEQ(num1, num2)); +} + +//ÕûÐÎÀàÐͰ²È«ÅжϴóÓÚµÈÓÚ +template +inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool +>::type IntGTE(Ty1 num1, Ty2 num2) +{ + return !IntLT(num1, num2); +} + +//ÕûÐÎÀàÐͰ²È«Åжϲ»µÈÓÚ +template +inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool +>::type IntNEQ(Ty1 num1, Ty2 num2) +{ + return !IntEQ(num1, num2); +} +#undef _IS_INT_TYPE +#undef _INT_SIGN_UNSIGN + + + +//¸¡µãÊý±È½Ï¸¨Öúºê +#define _FLOAT_DEFAULT_ULP 10 +#define _FLOAT_DEFAULT_ABS_MODE true +#define _IS_FLOAT_TYPE(Ty1, Ty2) \ + (std::is_floating_point::value && std::is_floating_point::value) +#define _FLOAT_COMMON_EPSILON(Ty1, Ty2) \ + (std::max(std::numeric_limits::epsilon(), std::numeric_limits::epsilon())) +#define _FLOAT_COMMON_MIN(Ty1, Ty2) \ + (std::max(std::numeric_limits::min(), std::numeric_limits::min())) +#define _FLOAT_ABS(num) ((num)>=0? (num):-(num)) + +//¸¡µãÊý±È½ÏÏàµÈ£¬±£Ö¤Âß¼­¹ØÏµ +template +inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool +>::type FloatEQ(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + return bAbs ? + (_FLOAT_ABS(num1-num2)<_FLOAT_COMMON_EPSILON(Ty1, Ty2)*ulp) + : + (_FLOAT_ABS(num1-num2)<_FLOAT_COMMON_EPSILON(Ty1, Ty2) + *(_FLOAT_ABS(num1)+_FLOAT_ABS(num2))*ulp + || _FLOAT_ABS(num1-num2)<_FLOAT_COMMON_MIN(Ty1, Ty2)*ulp); +} + +//¸¡µãÊý±È½ÏСÓÚ£¬±£Ö¤Âß¼­¹ØÏµ +template +inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool +>::type FloatLT(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + return num1 +inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool +>::type FloatLTE(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + return FloatLT(num1, num2, bAbs, ulp) || FloatEQ(num1, num2, bAbs, ulp); +} + +//¸¡µãÊý±È½Ï´óÓÚ£¬±£Ö¤Âß¼­¹ØÏµ +template +inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool +>::type FloatGT(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + return !(FloatLT(num1, num2, bAbs, ulp) || FloatEQ(num1, num2, bAbs, ulp)); +} + +//¸¡µãÊý±È½Ï´óÓÚµÈÓÚ£¬±£Ö¤Âß¼­¹ØÏµ +template +inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool +>::type FloatGTE(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + return !FloatLT(num1, num2, bAbs, ulp); +} + +//¸¡µãÊý±È½Ï²»µÈÓÚ£¬±£Ö¤Âß¼­¹ØÏµ +template +inline constexpr typename std::enable_if<_IS_FLOAT_TYPE(Ty1, Ty2), bool +>::type FloatNEQ(Ty1 num1, Ty2 num2, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + return !FloatEQ(num1, num2, bAbs, ulp); +} + + +//¸¡µãÊýÏÂת»¯ÕûÊý +template +inline typename std::enable_if::value, Ty +>::type FloatFloor(Ty num, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + Ty res = std::round(num); + if(FloatEQ(num, res, bAbs, ulp)) + return res; + return std::floor(num); +} + +//¸¡µãÊýÉÏת»¯ÕûÊý +template +inline typename std::enable_if::value, Ty +>::type FloatCeil(Ty num, bool bAbs= _FLOAT_DEFAULT_ABS_MODE, int ulp= _FLOAT_DEFAULT_ULP) +{ + Ty res = std::round(num); + if(FloatEQ(num, res, bAbs, ulp)) + return res; + return std::ceil(num); +} +#undef _FLOAT_DEFAULT_ULP +#undef _IS_FLOAT_TYPE +#undef _FLOAT_COMMON_EPSILON +#undef _FLOAT_COMMON_MIN +#undef _FLOAT_ABS + + + +//stringµÄÀÛ¼Ó²Ù×÷£¬Ê¹ÓÃ×óÒÆÔËËã·û +template +inline std::string &operator <<(std::basic_string &str, Ty &&arg) +{ + return str += std::forward(arg); +} + + + +//·¶Î§ÄÚ×ÖµäÐò±È½Ï²Ù×÷£¬Ê¹Óõü´úÆ÷£¬Ð¡ÓÚµÈÓÚ´óÓڷֱ𷵻Ø-1,0,1 +template::type, + typename IteratorRemoveCVRefDerefType::type>, + typename TyEqual= GeneralEqualTo::type, + typename IteratorRemoveCVRefDerefType::type> +> inline int SequenceCompare(TyIt1 st1, TyIt1 ed1, TyIt2 st2, TyIt2 ed2, + TyLess funcLess= TyLess(), TyEqual funcEqual= TyEqual()) +{ + for(; ; ++st1, ++st2) { + //ÅжϽáÊøÌõ¼þ + if(st1==ed1) { + if(st2==ed2) + return 0; + else + return -1; + } + else if(st2==ed2) + return 1; + //ÅжϴóС + if(funcLess(*st1, *st2)) + return -1; + else if(!(funcEqual(*st1, *st2))) + return 1; + } +} + + + +//¼ì²éÊÇ·ñΪtupleÀà +template +struct IsTupleType: + std::false_type +{ +}; +template +struct IsTupleType>: + std::true_type +{ +}; + + +//tupleÀàÐÍת»»À©Õ¹¸¨Öúº¯Êý +template +inline TyDst _TupleCastAssist(TySrc &&src, IndexSequence) +{ + return TyDst(std::get(std::forward(src))...); +} +//tupleÀàÐÍת»»À©Õ¹£¬Ö±½ÓÍêÃÀת·¢ÒÔÖ§³ÖËùÓеÄÒýÓÃÇé¿ö£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë +//Ô´ÀàÐÍÐèÒªÄܱ»getº¯Êý²ð½â£¬Ä¿µÄÀàÐÍÐèÒªÄܽÓÊÜÔ´ÀàÐͲð½âºóµÄ¹¹Ô캯Êý +template +inline TyDst TupleCast(TySrc &&src) +{ + return _TupleCastAssist(std::forward(src), MakeIndexSequence< + std::tuple_size::type>::value>()); +} + + + +//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐ͸¨ÖúÀàÐÍ +template +struct _TupleInvokeReturnTypeAssist +{ +}; +template +struct _TupleInvokeReturnTypeAssist> +{ + using type = decltype(std::declval()(std::get(std::declval())...)); +}; +//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐÍ£¬Ê¹ÓôøcvrefµÄÀàÐÍ´«Èë +template +struct TupleInvokeReturnType +{ + using type = typename _TupleInvokeReturnTypeAssist::type>::value>>::type; +}; + +//tupleÀàÐ͵÷Óú¯Êý¸¨Öúº¯Êý +template +inline typename TupleInvokeReturnType::type _TupleInvokeAssist(TyFunc &&func, TyTup &&tup, IndexSequence) +{ + return std::forward(func)(std::get(std::forward(tup))...); +} +//tupleÀàÐ͵÷Óú¯Êý£¬±¾ÖÊÉÏÖ»ÒªÄܱ»getº¯Êý²ð½â¼´¿É£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë +template +inline typename TupleInvokeReturnType::type TupleInvoke(TyFunc &&func, TyTup &&tup) +{ + return _TupleInvokeAssist(std::forward(func), std::forward(tup), + MakeIndexSequence::type>::value>()); +} + + + +//hashµ÷Óú¯Êý +template +inline auto HashFunc(Ty &&arg)-> +decltype(std::hash::type>()(std::forward(arg))) +{ + return std::hash::type>()(std::forward(arg)); +} + + +//hashµÄÌØÀý»¯ +namespace std +{ +//¶ÔpairÌØÀý»¯£¬Ã»Óн»»»²»±äÐÔ£¬Óëtuple¼æÈÝ +template +struct hash> +{ + typedef size_t result_type; + typedef std::pair argument_type; + result_type operator()(const argument_type &pr) const + { + return HashFunc(HashFunc(pr.first)) + ^ HashFunc(pr.second); + } +}; + +//¶ÔtupleÌØÀý»¯£¬Ã»Óн»»»²»±äÐÔ +template +struct hash> +{ + typedef size_t result_type; + typedef std::tuple argument_type; + result_type operator()(const argument_type &tup) const + { + return Assist(tup); + } +private: + template + static typename std::enable_if=2, result_type + >::type Assist(const std::tuple &tup) + { + return HashFunc(Assist(tup)) + ^ HashFunc(std::get(tup)); + } + template + static typename std::enable_if::type Assist(const std::tuple &tup) + { + return HashFunc(std::get<0>(tup)); + } + template + static typename std::enable_if::type Assist(const std::tuple &tup) + { + return 0; + } +}; +} + + +//¸÷Ààµü´úÆ÷hashÀ࣬βºóµü´úÆ÷½âÒýÓò»°²È« +template +struct IteratorHash +{ + typedef size_t result_type; + typedef Ty argument_type; + result_type operator()(argument_type it) const + { + return std::hash()(&*it); + } +}; + + + +//¸÷Ààµü´úÆ÷±È½ÏÀ࣬βºóµü´úÆ÷½âÒýÓò»°²È« +template +struct IteratorLess +{ + typedef bool result_type; + typedef Ty first_argument_type; + typedef Ty second_argument_type; + result_type operator()(const first_argument_type &it1, + const second_argument_type &it2) const + { + return &*it1<&*it2; + } +}; +template +struct IteratorEuqalTo +{ + typedef bool result_type; + typedef Ty first_argument_type; + typedef Ty second_argument_type; + result_type operator()(const first_argument_type &it1, + const second_argument_type &it2) const + { + return &*it1==&*it2; + } +}; + + +//¸÷Ààµü´úÆ÷½âÒýÓÃÖµ±È½ÏÀà +template +struct IteratorDerefLess +{ + typedef bool result_type; + typedef Ty first_argument_type; + typedef Ty second_argument_type; + result_type operator()(const first_argument_type &it1, + const second_argument_type &it2) const + { + return *it1<*it2; + } +}; +template +struct IteratorDerefEuqalTo +{ + typedef bool result_type; + typedef Ty first_argument_type; + typedef Ty second_argument_type; + result_type operator()(const first_argument_type &it1, + const second_argument_type &it2) const + { + return *it1==*it2; + } +}; + + + +//×Ö·ûÊý×ÖÅÐ¶Ï +inline constexpr bool IsNumChar(char ch) +{ + return ch>='0' && ch<='9'; +} +inline constexpr bool IsNotNumChar(char ch) +{ + return !IsNumChar(ch); +} +//×Ö·û´óд×ÖĸÅÐ¶Ï +inline constexpr bool IsUppChar(char ch) +{ + return (ch>='A' && ch<='Z'); +} +inline constexpr bool IsNotUppChar(char ch) +{ + return !IsUppChar(ch); +} +//×Ö·û´óд×ÖĸÅÐ¶Ï +inline constexpr bool IsLowChar(char ch) +{ + return (ch>='a' && ch<='z'); +} +inline constexpr bool IsNotLowChar(char ch) +{ + return !IsLowChar(ch); +} +//×Ö·û×ÖĸÅÐ¶Ï +inline constexpr bool IsLetChar(char ch) +{ + return IsUppChar(ch) || IsLowChar(ch); +} +inline constexpr bool IsNotLetChar(char ch) +{ + return !IsLetChar(ch); +} +//×Ö·ûÊý×Ö×ÖĸÅÐ¶Ï +inline constexpr bool IsNumLetChar(char ch) +{ + return IsNumChar(ch) || IsLetChar(ch); +} +inline constexpr bool IsNotNumLetChar(char ch) +{ + return !IsNumLetChar(ch); +} +//×Ö·û±êʶ·ûÅÐ¶Ï +inline constexpr bool IsIdChar(char ch) +{ + return IsNumLetChar(ch) || (ch=='_'); +} +inline constexpr bool IsNotIdChar(char ch) +{ + return !IsIdChar(ch); +} +//×Ö·ûÊ®Áù½øÖÆÅÐ¶Ï +inline constexpr bool IsHexChar(char ch) +{ + return (ch>='0' && ch<='9') + || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); +} +inline constexpr bool IsNotHexChar(char ch) +{ + return !IsHexChar(ch); +} +//×Ö·ûasciiÅÐ¶Ï +inline constexpr bool IsAsciiChar(char ch) +{ + return ch>=0x00 && ch<=0x7F; +} +inline constexpr bool IsNotAsciiChar(char ch) +{ + return !IsAsciiChar(ch); +} +//×Ö·û¹ãÒå±êʶ·ûÅÐ¶Ï +inline constexpr bool IsBroadIdChar(char ch) +{ + return IsIdChar(ch) || IsNotAsciiChar(ch); +} +inline constexpr bool IsNotBroadIdChar(char ch) +{ + return !IsBroadIdChar(ch); +} +//×Ö·û¿Õ°×·ûÅÐ¶Ï +inline constexpr bool IsBlankChar(char ch) +{ + return ch==' ' || ch=='\t' || ch=='\r' || ch=='\n' + || ch=='\v' || ch=='\f'; +} +inline constexpr bool IsNotBlankChar(char ch) +{ + return !IsBlankChar(ch); +} + + +//Сд×Öĸת»»´óд×Öĸ +inline constexpr char LowCharToUppChar(char ch) +{ + return (char) + (IsLowChar(ch) ? + 'A'+(ch-'a') + : + ch); +} +//´óд×ÖĸתСд×Öĸ +inline constexpr char UppCharToLowChar(char ch) +{ + return (char) + (IsUppChar(ch) ? + 'a'+(ch-'A') + : + ch); +} + + +//Êý×Ö×Ö·ûת»¯Êý×Ö +inline constexpr int NumCharToNum(char ch) +{ + return IsNumChar(ch) ? + ch-'0' + : + -1; +} +//×Öĸ×Ö·ûת»¯Êý×Ö +inline constexpr int LetCharToNum(char ch) +{ + return IsLowChar(ch) ? + ch-'a' + : IsUppChar(ch) ? + ch-'A' + : + -1; +} +//Ê®Áù½øÖÆ×Ö·ûת»¯Êý×Ö +inline constexpr int HexCharToNum(char ch) +{ + return (ch>='0' && ch<='9') ? + ch-'0' + : (ch>='a' && ch<='f') ? + ch-'a'+10 + : (ch>='A' && ch<='F') ? + ch-'A'+10 + : + -1; +} + + +//Êý×Öת»¯Êý×Ö×Ö·û +inline constexpr char NumToNumChar(int i) +{ + return (char) + ((i>=0 && i<=9) ? + i+'0' + : + 0); +} +//Êý×Öת»¯´óд×Öĸ×Ö·û +inline constexpr char NumToUppChar(int i) +{ + return (char) + ((i>=0 && i<=25) ? + i+'A' + : + 0); +} +//Êý×Öת»¯Ð¡Ð´×Öĸ×Ö·û +inline constexpr char NumToLowChar(int i) +{ + return (char) + ((i>=0 && i<=25) ? + i+'a' + : + 0); +} +//Êý×Öת»¯´óдʮÁù½øÖÆ×Ö·û +inline constexpr char NumToUppHexChar(int i) +{ + return (char) + ((i>=0 && i<=9) ? + i+'0' + : (i>=10 && i<=15) ? + i+'A' + : + 0); +} +//Êý×Öת»¯Ð¡Ð´Ê®Áù½øÖÆ×Ö·û +inline constexpr char NumToLowHexChar(int i) +{ + return (char) + ((i>=0 && i<=9) ? + i+'0' + : (i>=10 && i<=15) ? + i+'a' + : + 0); +} + diff --git a/UsedMacro.h b/UsedMacro.h new file mode 100644 index 0000000..44fc75a --- /dev/null +++ b/UsedMacro.h @@ -0,0 +1,166 @@ +#pragma once + +//³£Óú궨Òå¿â +//20191111-1705 + +#include +#include + +#include + +#include +#include + +#include + +#include +#include + + +//********** +//±êʶ·û²Ù×÷ +//********** + +#define SYMBOL_STR(id) #id//ת±ä×Ö·û´® + + + +#define CONNECT_SYMBOL_2(str1, str2) str1##str2 +#define CONNECT_SYMBOL_3(str1, str2, str3) str1##str2##str3 +#define CONNECT_SYMBOL_4(str1, str2, str3, str4) str1##str2##str3##str4 + + + +//************ +//ÊýÖµÔËËã²Ù×÷ +//************ + +#define NEG_TO(x) ((x) = -(x))//¸³Ïà·´Êý +#define NOT_TO(x) ((x) = !(x))//¸³²¼¶û·Ç +#define INV_TO(x) ((x) = ~(x))//¸³°´Î»È¡·´ + + +#define ABS_OF(x) ((x)>0? (x):-(x))//È¡¾ø¶ÔÖµ +#define ABS_TO(x) ((x) = ABS_OF(x))//¸³¾ø¶ÔÖµ + + +#define DIS_OF(x, y) (ABS_OF((x)-(y)))//È¡²îÖµ + + + +#define MAX_OF(x, y) ((x)>(y)? (x):(y))//È¡×î´óÖµ +#define MIN_OF(x, y) ((x)<(y)? (x):(y))//È¡×îСֵ + + +#define MAX_TO(x, lim) ((x) = MAX_OF(x, lim))//¸³×î´óÖµ +#define MIN_TO(x, lim) ((x) = MIN_OF(x, lim))//¸³×îСֵ + +#define HIGH_LIMIT(x, lim) MIN_TO(x, lim)//ÉèÖÃÉÏÏÞ +#define LOW_LIMIT(x, lim) MAX_TO(x, lim)//ÉèÖÃÏÂÏÞ + + +#define RANGE_OF(x, llim, hlim) ((x)<(llim)? (llim): (x)>(hlim)? (hlim):(x))//È¡·¶Î§ +#define RANGE_LIMIT(x, llim, hlim) ((x) = RANGE_OF(x, llim, hlim))//ÉèÖ÷¶Î§ + + +#define IS_IN_RANGE(x, llim, hlim) ((x)>=(llim) && (x)<=(hlim))//ÅжÏÊÇ·ñÔÚ·¶Î§ÄÚ +#define IS_IN_ITER_RANGE(x, st, ed) ((x)>=(st) && (x)<(ed))//ÅжÏÊÇ·ñÔÚ·¶Î§ÄÚ£¬ÒÔµü´úÆ÷±ê×¼ + + + +#define SQUARE_OF(x) ((x)*(x))//Ç󯽷½ +#define SQUARE_TO(x) ((x) = SQUARE_OF(x))//¸³ÖµÆ½·½ + + + +//************ +//ÔËËãÊ¡ÂÔ²Ù×÷ +//************ + + + +#define LIST_GO(p, m_p) ((p) = (p)->m_p)//Á´±íÖ¸ÕëÒÆ¶¯ + +#define LIST_CNNT(p1, m_p1, p2, m_p2) \ + (((p1)->m_p1=p2), ((p2)->m_p2=p1))//Ë«ÏòÁ´±íÁ¬½Ó + +#define LIST_ADD(p1, m_p1, p2, m_p2, pNew) \ + (LIST_CNNT(p1, m_p1, pNew, m_p2), LIST_CNNT(pNew, m_p1, p2, m_p2))//Ë«ÏòÁ´±íÌí¼Ó + + + +#define ARR_SIZE(arr) (sizeof(decltype(arr))\ + /sizeof(typename std::remove_extent::type))//ÇóÊý×é´óС + +#define ARR_SIZE_ALL(arr) (sizeof(decltype(arr))\ + /sizeof(typename std::remove_all_extents::type))//Çó¸ùÊý×é´óС + + + +#define SHOW_BEGIN_END(container) std::begin(container), std::end(container)//ÁгöÈÝÆ÷µÄbeginºÍendº¯Êý + + + +#define O_(id) CONNECT_SYMBOL_2(o_, id)//Ìí¼Óԭʼǰ׺ + +#define O_INIT(id) id(O_(id))//ʹÓÃǰ׺°æ±¾³õʼ»¯ +#define O_INIT_MOVE(id) id(std::move(O_(id)))//ʹÓÃǰ׺°æ±¾Òƶ¯³õʼ»¯ +#define O_INIT_FORWARD(id, Ty) id(std::forward(O_(id)))//ʹÓÃǰ׺°æ±¾×ª·¢³õʼ»¯ + +#define O_ASSIGN(id) (id = O_(id))//ʹÓÃǰ׺°æ±¾¸³Öµ +#define O_ASSING_MOVE(id) (id = std::move(O_(id)))//ʹÓÃǰ׺°æ±¾Òƶ¯¸³Öµ +#define O_ASSIGN_FORWARD(id, Ty) (id = std::forward(O_(id)))//ʹÓÃǰ׺°æ±¾×ª·¢³õʼ»¯ + + +#define OTHER_INIT(other, mem) mem((other).mem)//ʹÓÃÀà³ÉÔ±³õʼ»¯ +#define OTHER_INIT_MOVE(other, mem) mem(std::move(other).mem)//ʹÓÃÀà³ÉÔ±ÒÆ¶¯³õʼ»¯ +#define OTHER_INIT_FORWARD(other, mem, Ty) mem(std::forward(other).mem)//ʹÓÃÀà³ÉԱת·¢³õʼ»¯ + +#define OTHER_ASSIGN(other, mem) (mem = (other).mem)//ʹÓÃÀà³ÉÔ±¸³Öµ +#define OTHER_ASSIGN_MOVE(other, mem) (mem = std::move(other).mem)//ʹÓÃÀà³ÉÔ±ÒÆ¶¯¸³Öµ +#define OTHER_ASSIGN_FORWARD(other, mem) (mem = std::forward(other).mem)//ʹÓÃÀà³ÉԱת·¢¸³Öµ + + + +//****** +//¶àÓï¾ä²Ù×÷ +//****** + +#define CLASS_ASSIGN(Type, other) {\ + if(this!=&(other)) {\ + this->~Type();\ + new(this) Type(other);\ + }}//¿½±´¸³Öµ£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + +#define CLASS_ASSIGN_MOVE(Type, other) {\ + if(this!=&(other)) {\ + this->~Type();\ + new(this) Type(std::move(other));\ + }}//ÒÆ¶¯¸³Öµ£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + + +#define TEMPLATE_ASSIGN(Type, Typename, arg) {\ + this->~Type();\ + new(this) Type(std::forward(arg));\ + }//Ä£°å¸³Öµ£¬×Ô¸³Öµ²»°²È«£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + +#define TEMPLATE_PACKET_ASSIGN(Type, Typenames, args) {\ + this->~Type();\ + new(this) Type(std::forward(args)...);\ + }//Ä£°å°ü¸³Öµ£¬×Ô¸³Öµ²»°²È«£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓà + + + +//****** +//ÉùÃ÷²Ù×÷ +//****** + +#define DEFINE_INLINE_VERIABLE(Type, name) \ +inline Type &name() \ +{\ + static Type value;\ + return value;\ +}//¶¨ÒåÄÚÁª±äÁ¿ + +#define GET_INLINE_VARIABLE(name) name()//»ñÈ¡ÄÚÁª±äÁ¿ + diff --git a/makefile b/makefile new file mode 100644 index 0000000..31a5762 --- /dev/null +++ b/makefile @@ -0,0 +1,49 @@ +#编译器版本 +CC = gcc +CXX = g++ -std=c++11 +#附加头文件目录 +INCS_DIR = +#附加包含库目录 +LIBS_DIR = +#附加包含库文件 +DEF_LIBS = +STA_LIBS = +DYN_LIBS = +#预定义宏 +DEFINE = -D MAKEFILE_ENVIRONMENT +#编译选项 +CFLAGS = -g -Wall -O3 + +#目标生成文件名 +TARGETS = DomainDeal +#源文件 +C_SRCS = $(wildcard *.c */*.c) +CPP_SRCS = $(wildcard *.cpp */*.cpp) +#中间文件 +C_OBJS = $(patsubst %.c,%.o,$(C_SRCS)) +CPP_OBJS = $(patsubst %.cpp,%.o,$(CPP_SRCS)) +#依赖头文件 +HEADS = $(wildcard *.h */*.h *.hpp */*.hpp) + + +#生成目标 +$(TARGETS): $(C_OBJS) $(CPP_OBJS) + $(CXX) -o $@ $(CFLAGS) $(LIBS_DIR) $(C_OBJS) $(CPP_OBJS) \ + $(DEF_LIBS) -Wl,-Bstatic $(STA_LIBS) -Wl,-Bdynamic $(DYN_LIBS) + +#c生成.o +$(C_OBJS): %.o: %.c $(HEADS) + $(CC) -c $(CFLAGS) $(INCS_DIR) $(DEFINE) $(patsubst %.o,%.c,$@) +#cpp生成.o +$(CPP_OBJS): %.o: %.cpp $(HEADS) + $(CXX) -c $(CFLAGS) $(INCS_DIR) $(DEFINE) $(patsubst %.o,%.cpp,$@) + + +#清理文件命令 +.PHONY: clean +clean: + -rm $(TARGETS) $(C_OBJS) $(CPP_OBJS) + +#重构文件命令 +.PHONY: rebuild +rebuild: clean $(TARGETS) \ No newline at end of file diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..34d3196 --- /dev/null +++ b/test.txt @@ -0,0 +1,5 @@ +this is head line +0 www.baidu.com 3 4 5 6 7 8 9 10 11 12 13 14 etc +0 1 www.google.com 3 4 5 6 7 8 9 10 11 12 13 14 +0 1 youku.com 3 4 5 6 7 8 9 10 11 12 13 14 etc +