summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author张硕 <[email protected]>2019-12-31 11:11:28 +0800
committer张硕 <[email protected]>2019-12-31 11:11:28 +0800
commitaf96ee359d85fcb1c64dac645bc68199d39d0651 (patch)
treebbc01d6c51de0ae94ed7cbf4ef6946acd8b222c0
parent6fe2e67322cbbbc849c68b930d1b1c1a00b27aec (diff)
Update IoOperator.h, makefile, StruAndAlgo.h, test.txt, TypeExtend.h, UsedMacro.h files
-rw-r--r--IoOperator.h1606
-rw-r--r--StruAndAlgo.h2562
-rw-r--r--TypeExtend.h1280
-rw-r--r--UsedMacro.h166
-rw-r--r--makefile49
-rw-r--r--test.txt5
6 files changed, 5668 insertions, 0 deletions
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 <cstdint>
+#include <cassert>
+
+#include <iostream>
+#include <fstream>
+
+#include <limits>
+#include <type_traits>
+#include <algorithm>
+#include <initializer_list>
+#include <utility>
+#include <tuple>
+#include <iterator>
+
+#include <string>
+#include <vector>
+#include <array>
+#include <deque>
+#include <list>
+#include <set>
+#include <map>
+#include <unordered_set>
+#include <unordered_map>
+
+#include <exception>
+#include <stdexcept>
+
+#include <mutex>
+
+
+//¿â¹ØÁªÐèÇóÎļþ
+#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<ritWordEd.base())
+ strValue.assign(itWordSt, ritWordEd.base());
+ return true;
+}
+
+
+
+//ÊäÈëÁ÷¶ÁÈ¡ÅäÖÃÎļþ£¬ÓÐÔ¤¶¨Òå×ֶη¶Î§£¬¶ÁÈ¡·¶Î§ÄÚµÄÖµ£¬·µ»ØÎ´ÕÒµ½µÄµÚÒ»¸ö×Ö¶Î
+//ÅäÖÃÎļþ¸ñʽӦΪȥµô"#define"µÄºê¶¨Òå¸ñʽ£¬'#'';'"//"¶¼Îª×¢ÊÍ
+//bReplaceÊÇ·ñͬһ×ֶκóÕßÌæ»»Ç°Õߣ¬ÈôÎªÖØ¸´¼¯ºÏÇÒΪ·ñÔòÖØ¸´Ìí¼Ó
+//bCheckNullÊÇ·ñ¾Ü¾ø¶ÁȡֵΪ¿ÕµÄÇé¿ö
+template<typename Ty1, typename Ty2>
+inline Ty2 StreamReadPredefInit(std::istream &is, Ty1 &table,
+ Ty2 itFieldSt, Ty2 itFieldEd, bool bReplace= true, bool bCheckNull= true)
+{
+ //½«¹Ø¼ü×Ö¶ÎдÈë
+ Ty2 itField;
+ std::set<std::string> 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<typename Ty1>
+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<char> &(*func)(std::basic_ostream<char> &))
+{
+ bool res = (bool)is;
+ if(func==&std::flush<char, std::char_traits<char>>)
+ is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+ else if(func==&std::ends<char, std::char_traits<char>>)
+ is.clear();
+ else if(func==&std::endl<char, std::char_traits<char>>) {
+ is.clear();
+ is.ignore(std::numeric_limits<std::streamsize>::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<typename Ty>
+class OstreamHold
+{
+ OstreamHold()
+ = delete;
+};
+//Êä³öÁ÷±£³ÖÀà×óÖµÒýÓÃÌØ»¯
+template<typename Ty>
+class OstreamHold<Ty &>
+{
+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<Ty &> &)
+ = delete;
+ OstreamHold<Ty &> &operator =(const OstreamHold<Ty &> &)
+ = delete;
+ //ĬÈÏÒÆ¶¯
+ OstreamHold(OstreamHold<Ty &> &&)
+ = default;
+ OstreamHold<Ty &> &operator =(OstreamHold<Ty &> &&)
+ = default;
+ //Á÷ÒýÓÃ
+ std::ostream &operator()() const
+ {
+ return os;
+ }
+ //ÒýÓúͳÉÔ±ÒýÓÃ
+ Ty &operator *() const
+ {
+ return ref;
+ }
+ Ty *operator ->() const
+ {
+ return &ref;
+ }
+ //ת»»³£ÀàÐͰ汾
+ operator OstreamHold<const Ty &>() const
+ {
+ return OstreamHold<const Ty &>(os, ref);
+ }
+};
+//Êä³öÁ÷±£³ÖÀàÓÒÖµÒýÓÃÌØ»¯
+template<typename Ty>
+class OstreamHold<Ty &&>
+{
+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<Ty &&> &)
+ = delete;
+ OstreamHold<Ty &&> &operator =(const OstreamHold<Ty &&> &)
+ = delete;
+ //ĬÈÏÒÆ¶¯
+ OstreamHold(OstreamHold<Ty &&> &&)
+ = default;
+ OstreamHold<Ty &&> &operator =(OstreamHold<Ty &&> &&)
+ = default;
+ //ת»»×óÖµÁ÷
+ OstreamHold<const Ty &> operator()() const
+ {
+ return OstreamHold<const Ty &>(os, data);
+ }
+ OstreamHold<Ty &> operator()()
+ {
+ return OstreamHold<Ty &>(os, data);
+ }
+ //ÒýÓúͳÉÔ±ÒýÓÃ
+ Ty &operator *() const
+ {
+ return data;
+ }
+ Ty *operator ->() const
+ {
+ return &data;
+ }
+};
+
+
+
+//Êä³öÁ÷¼¯ºÏÎÞËø±êÖ¾£¬×÷ΪÁ÷Êä³ö±íʾÎÞËø
+class OstreamSetNoLock
+{
+};
+
+//Êä³öÁ÷¼¯ºÏÀà
+//ÓÃÓÚ¶à¸öÊä³öÁ÷ͬʱÊä³ö£¬Ö§³Ö·ÇÁ÷ÒýÓ÷µ»ØÖµµÄ´«µÝÁ÷²Ù×÷
+//¸½¼Ó»¥³âËø¹¦Äܽӿڣ¬ÒªÇó²ÎÊý¿ÉËøÀàÐÍ£¬Í¬Ê±´ËÀàÒ²Âú×ã¿ÉËø
+//ÈôÓÐËøÔòÁ÷²Ù×÷×Ô¶¯£¬³ý·Ç´«µÝ·ÇËø±êÖ¾£¬ÔÚÒ»´®Á÷²Ù×÷¿ªÊ¼½áÊøÊ±½øÐÐËø¶¨½âËø
+template<typename TyMtx= std::mutex>
+class OstreamSet
+{
+public:
+ //Êä³ö¼¯ºÏ´«µÝÀàÐÍ
+ template<typename TyRes>
+ class Hold;
+
+public:
+ std::vector<std::ostream *> vecPOs;//Êä³öÁ÷£¬¸ü¸Ä·ÇḬ̈߳²È«
+ std::vector<TyMtx *> 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<std::ostream *> intlOs,
+ std::initializer_list<TyMtx *> intlMtx = {}
+ ): vecPOs(intlOs), vecPMtx(intlMtx)
+ {
+ }
+ //µü´úÆ÷¹¹Ôì
+ template<typename TyItOs, typename TyItMtx>
+ 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<typename TyItOs>
+ explicit OstreamSet(TyItOs itOsSt, TyItOs itOsEd):
+ OstreamSet(itOsSt, itOsEd, (TyMtx *)nullptr, (TyMtx *)nullptr)
+ {
+ }
+public:
+ //ת·¢Á÷²Ù×÷£¬Ḭ̈߳²È«£¬°´Ë³Ðòµ÷ÓÃËø£¬Ðè±£Ö¤²»ËÀËø
+ template<typename Ty>
+ auto operator <<(Ty &&arg) const->
+ Hold<decltype(*vecPOs.front()<<std::forward<Ty>(arg))>
+ {
+ //Á÷½á¹ûÀàÐÍÊý×é
+ using TyRes = decltype(*vecPOs.front()<<std::forward<Ty>(arg));
+ std::vector<TypeHolder<TyRes>> vecRes;
+ vecRes.reserve(vecPOs.size());
+ //µ÷ÓÃËø¶¨
+ Lock();
+ //Êä³ö²¢´æ´¢
+ for(auto pOs : vecPOs) {
+ vecRes.emplace_back(*pOs <<std::forward<Ty>(arg));
+ }
+ //Éú³É½á¹ûµÄHoldÀàÐÍ
+ return Hold<TyRes>(std::move(vecRes), vecPMtx.empty()? nullptr:this);
+ }
+ //¶Ô²Ù×÷·û½øÐÐת·¢
+ template<int c_blank =0>
+ auto operator <<(std::ios_base &(*func)(std::ios_base &)) const->
+ decltype(this->operator << <decltype((func))>(func))
+ {
+ return operator << <decltype((func))>(func);
+ }
+ template<int c_blank =0>
+ auto operator <<(std::basic_ios<char> &(*func)(std::basic_ios<char> &)) const->
+ decltype(this->operator << <decltype((func))>(func))
+ {
+ return operator << <decltype((func))>(func);
+ }
+ template<int c_blank =0>
+ auto operator <<(
+ std::basic_ostream<char> &(*func)(std::basic_ostream<char> &)) const->
+ decltype(this->operator << <decltype((func))>(func))
+ {
+ return operator << <decltype((func))>(func);
+ }
+ //¶Ô²»Ëø±êÖ¾½øÐÐÁ÷²Ù×÷£¬Á÷Êä³ö½«²»½øÐÐËø¶¨ºÍ½âËø
+ Hold<std::ostream &> operator <<(OstreamSetNoLock) const
+ {
+ //Á÷½á¹ûÀàÐÍÊý×é
+ using TyRes = std::ostream &;
+ std::vector<TypeHolder<TyRes>> vecRes;
+ vecRes.reserve(vecPOs.size());
+ //´æ´¢ÀàÐÍ
+ for(auto pOs : vecPOs) {
+ vecRes.emplace_back(*pOs);
+ }
+ //Éú³É½á¹ûµÄHoldÀàÐÍ
+ return Hold<TyRes>(std::move(vecRes), nullptr);
+ }
+ //µ÷ÓÃostreamµÄ³ÉÔ±º¯Êý£¬½øÐÐËø¶¨£¬ºöÂÔ·µ»ØÖµ
+ template<typename Ty, typename ...Tys>
+ void operator()(const Ty &pmf, Tys &&...args) const
+ {
+ //µ÷ÓÃËø¶¨
+ Lock();
+ //µ÷ÓóÉÔ±º¯Êý
+ for(auto pOs : vecPOs) {
+ (pOs->*pmf)(std::forward<Tys>(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; i<vecPMtx.size(); ++i) {
+ if(!vecPMtx[i]->try_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<typename TyMtx>
+template<typename TyRes>
+class OstreamSet<TyMtx>::Hold
+{
+ friend class OstreamSet<TyMtx>;
+private:
+ std::vector<TypeHolder<TyRes>> vecRes;//Êä³öÁ÷µÄ½á¹ûÊý×é
+ const OstreamSet<TyMtx> *pSet;//Êä³öÁ÷¼¯ºÏÖ¸Õ룬Îö¹¹½âËø±êÖ¾
+
+private:
+ //¹¹Ô죬Êä³ö¼¯ºÏÒýÓóõʼ»¯
+ explicit Hold(std::vector<TypeHolder<TyRes>> &&o_vecRes,
+ const OstreamSet<TyMtx> *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<typename Ty>
+ auto operator <<(Ty &&arg)->
+ Hold<decltype(vecRes.front().hold<<std::forward<Ty>(arg))>
+ {
+ //´Ë¶ÔÏó²»ÐèÎö¹¹½âËø
+ auto ptr = pSet;
+ pSet = nullptr;
+ //еÄÁ÷²Ù×÷½á¹ûÀàÐÍ
+ using TyResTmp = decltype(vecRes.front().hold<<std::forward<Ty>(arg));
+ std::vector<TypeHolder<TyResTmp>> vecResTmp;
+ vecResTmp.reserve(vecRes.size());
+ //Á÷Êä³ö²¢´æ´¢
+ for(auto &refRes : vecRes) {
+ vecResTmp.emplace_back(refRes.hold <<std::forward<Ty>(arg));
+ }
+ //¹¹ÔìеÄHoldÀàÐÍ£¬×ªÒåÎö¹¹½âËø±êÖ¾
+ return Hold<TyResTmp>(std::move(vecResTmp), ptr);
+ }
+ //¶Ô²Ù×÷·û½øÐÐת·¢
+ template<int c_blank =0>
+ auto operator <<(std::ios_base &(*func)(std::ios_base &))->
+ decltype(this->operator << <decltype((func))>(func))
+ {
+ return operator << <decltype((func))>(func);
+ }
+ template<int c_blank =0>
+ auto operator <<(std::basic_ios<char> &(*func)(std::basic_ios<char> &))->
+ decltype(this->operator << <decltype((func))>(func))
+ {
+ return operator << <decltype((func))>(func);
+ }
+ template<int c_blank =0>
+ auto operator <<(
+ std::basic_ostream<char> &(*func)(std::basic_ostream<char> &))->
+ decltype(this->operator << <decltype((func))>(func))
+ {
+ return operator << <decltype((func))>(func);
+ }
+};
+
+
+
+//¶ÏÑÔ²Ù×÷ÀàÊä³öÑ¡Ïî
+enum class AssertOption
+{
+ thrw_log,//Å׳öÒì³£²¢Êä³öÈÕÖ¾
+ thrw,//Å׳öÒì³£
+ asst_log,//µ÷ÊÔ¶ÏÑÔ²¢Êä³öÈÕÖ¾
+ asst,//µ÷ÊÔ¶ÏÑÔ
+ log,//Êä³öÈÕÖ¾
+ none,//ÎÞ²Ù×÷
+};
+
+//¶ÏÑÔ²Ù×÷Àà
+template<typename TyOs= std::ostream>
+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 <<str <<std::flush;
+ throw NoCatchError(str);
+ }
+ else if(optionTmp==AssertOption::thrw) {
+ throw NoCatchError(str);
+ }
+ else if(optionTmp==AssertOption::asst_log) {
+ os <<str <<std::flush;
+ assert(false);
+ }
+ else if(optionTmp==AssertOption::asst) {
+ assert(false);
+ }
+ else if(optionTmp==AssertOption::log) {
+ os <<str <<std::flush;
+ }
+ else if(optionTmp==AssertOption::none) {
+ }
+ return false;
+ }
+ //ʹÓÃĬÈÏÑ¡Ïî½øÐжÏÑÔ
+ bool operator()(bool bCond, const std::string &str= "") const
+ {
+ return operator()(option, bCond, str);
+ }
+};
+
+
+
+//дÀàÐͶþ½øÖÆÎļþÀà
+//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿
+class BinWriteFile
+{
+public:
+ std::ofstream ofs;//ÎļþÁ÷
+
+public:
+ //¹¹Ôì
+ BinWriteFile()
+ = default;
+ explicit BinWriteFile(const std::string &name, bool o_bAfter=false)
+ {
+ Open(name, o_bAfter);
+ }
+ //Îö¹¹
+ ~BinWriteFile()
+ = default;
+ //ɾ³ý¿½±´
+ BinWriteFile(const BinWriteFile &)
+ = delete;
+ BinWriteFile &operator =(BinWriteFile &)
+ = delete;
+ //ÒÆ¶¯¹¹Ôì
+ BinWriteFile(BinWriteFile &&file)
+ = default;
+ //ÒÆ¶¯¸³Öµ
+ BinWriteFile &operator =(BinWriteFile &&file)
+ = default;
+
+public:
+ //´ò¿ªÎļþ£¬o_bAfterÊÇ·ñ×·¼Óд
+ BinWriteFile &Open(const std::string &name, bool o_bAfter=false)
+ {
+ ofs.close();
+ if(o_bAfter)
+ ofs.open(name, std::ios::binary|std::ios::app);
+ else
+ ofs.open(name, std::ios::binary);
+ if(!ofs.is_open())
+ throw std::runtime_error("Can't Open Write File");
+ return *this;
+ }
+ //¹Ø±ÕÎļþ
+ bool Close()
+ {
+ ofs.close();
+ if(ofs.bad())
+ throw std::runtime_error("Can't Close File");
+ return true;
+ }
+ //·µ»Ø´ò¿ª×´Ì¬
+ bool isopen() const
+ {
+ return ofs.is_open();
+ }
+ //ÎļþÁ÷¿ÉÓã¬Ò»¶¨¿ÉÓÃ
+ bool IsFail() const
+ {
+ return !ofs.good();
+ }
+ operator bool() const
+ {
+ return ofs.good();
+ }
+ //Çå³ý´íÎó±êÖ¾
+ void Clear()
+ {
+ ofs.clear();
+ }
+ //Ë¢ÐÂÎļþ»º³åÇø
+ BinWriteFile &Fflush()
+ {
+ ofs.flush();
+ return *this;
+ }
+ //ÖØ¶¨Î»Î»ÖÃ
+ BinWriteFile &Seekp(std::ofstream::pos_type pos)
+ {
+ ofs.seekp(pos);
+ return *this;
+ }
+ BinWriteFile &Seekp(std::ofstream::off_type off, std::ios_base::seekdir dir)
+ {
+ ofs.seekp(off, dir);
+ return *this;
+ }
+ //²éѯλÖÃ
+ std::ofstream::pos_type Tellp()
+ {
+ return ofs.tellp();
+ }
+ //¶Ô»º³åÇø½øÐÐÎļþдÈë
+ BinWriteFile &WriteBuf(const void *buf, size_t size)
+ {
+ ofs.write(reinterpret_cast<const char *>(buf), size);
+ if(ofs.bad())
+ throw std::runtime_error("Can't Write File");
+ return *this;
+ }
+ //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
+ template<typename Ty>
+ typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile &
+ >::Type WriteArray(const Ty *pt, size_t count)
+ {
+ WriteBuf(pt, sizeof(Ty)*count);
+ return *this;
+ }
+ //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
+ template<typename Ty>
+ typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile &
+ >::Type WriteArray(const Ty *pt, size_t count)
+ {
+ for(; count!=0; --count, ++pt)
+ *this <<*pt;
+ return *this;
+ }
+public:
+ //¶ÔÄÚÖÃÀàÐͽøÐÐÎļþдÈ룬°üÀ¨ÄÚÖÃÀàÐÍÊý×é
+ template<typename Ty>
+ typename std::enable_if<std::is_scalar<
+ typename std::remove_all_extents<Ty>::type>::value, BinWriteFile &
+ >::type operator <<(const Ty &r)
+ {
+ WriteBuf(&r, sizeof(r));
+ return *this;
+ }
+ //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþдÈë
+ template<typename Ty, size_t N>
+ typename std::enable_if<!std::is_scalar<
+ typename std::remove_all_extents<Ty>::type>::value, BinWriteFile &
+ >::type operator <<(const Ty (&arrStr)[N])
+ {
+ for(int64_t i=0; i<N; ++i)
+ *this <<arrStr[i];
+ return *this;
+ }
+ //¶Ôpair½øÐÐÎļþдÈë
+ template<typename Ty1, typename Ty2>
+ BinWriteFile &operator <<(const std::pair<Ty1, Ty2> &pr)
+ {
+ *this <<pr.first <<pr.second;
+ return *this;
+ }
+ //¶Ôtuple½øÐÐÎļþдÈë
+ template<typename ...Tys>
+ BinWriteFile &operator <<(const std::tuple<Tys...> &tup)
+ {
+ TupleWrite<sizeof...(Tys)-1>(tup);
+ return *this;
+ }
+ template<int index, typename ...Tys>
+ typename std::enable_if<(index>=0), void
+ >::type TupleWrite(const std::tuple<Tys...> &tup)
+ {
+ *this <<std::get<index>(tup);
+ TupleWrite<index-1>(tup);
+ }
+ template<int index, typename Ty>
+ void TupleWrite(const Ty &tup)
+ {
+ }
+ //¶Ôstring½øÐÐÎļþдÈë
+ template<typename Ty>
+ BinWriteFile &operator <<(const std::basic_string<Ty> &str)
+ {
+ //д³ß´ç
+ int64_t size = str.size();
+ operator <<(size);
+ //дÊý¾Ý
+ WriteBuf(&str[0], (size_t)(size*sizeof(Ty)));
+ return *this;
+ }
+ //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþдÈë
+ template<typename Ty>
+ typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile &
+ >::type operator <<(const std::vector<Ty> &vec)
+ {
+ //д³ß´ç
+ int64_t size = vec.size();
+ operator <<(size);
+ //дÊý¾Ý
+ WriteBuf(vec.data(), size*sizeof(Ty));
+ return *this;
+ }
+ //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë
+ template<typename Ty>
+ typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile &
+ >::type operator <<(const std::vector<Ty> &vec)
+ {
+ //д³ß´ç
+ int64_t size = vec.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : vec)
+ *this <<r;
+ return *this;
+ }
+ //¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþдÈë
+ template<typename Ty, size_t c_size>
+ typename std::enable_if<std::is_scalar<Ty>::value, BinWriteFile &
+ >::type operator <<(const std::array<Ty, c_size> &arr)
+ {
+ //дÊý¾Ý
+ WriteBuf(arr.data(), c_size*sizeof(Ty));
+ return *this;
+ }
+ //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþдÈë
+ template<typename Ty, size_t c_size>
+ typename std::enable_if<!std::is_scalar<Ty>::value, BinWriteFile &
+ >::type operator <<(const std::array<Ty, c_size> &arr)
+ {
+ //дÊý¾Ý
+ for(auto &r : arr)
+ *this <<r;
+ return *this;
+ }
+ //¶Ôdeque½øÐÐÎļþдÈë
+ template<typename Ty>
+ BinWriteFile &operator <<(const std::deque<Ty> &deq)
+ {
+ //д³ß´ç
+ int64_t size = deq.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : deq)
+ *this <<r;
+ return *this;
+ }
+ //¶Ôlist½øÐÐÎļþдÈë
+ template<typename Ty>
+ BinWriteFile &operator <<(const std::list<Ty> &lis)
+ {
+ //д³ß´ç
+ int64_t size = lis.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : lis)
+ *this <<r;
+ return *this;
+ }
+ //¶Ô¶þ²æÊ÷½øÐÐÎļþдÈë
+ template<typename Ty, typename TyComp>
+ BinWriteFile &operator <<(const std::set<Ty, TyComp> &bst)
+ {
+ //д³ß´ç
+ int64_t size = bst.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : bst)
+ *this <<r;
+ return *this;
+ }
+ //¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþдÈë
+ template<typename Ty, typename TyComp>
+ BinWriteFile &operator <<(const std::multiset<Ty, TyComp> &bst)
+ {
+ //д³ß´ç
+ int64_t size = bst.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : bst)
+ *this <<r;
+ return *this;
+ }
+ //¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþдÈë
+ template<typename Ty1, typename Ty2, typename TyComp>
+ BinWriteFile &operator <<(const std::map<Ty1, Ty2, TyComp> &bst)
+ {
+ //д³ß´ç
+ int64_t size = bst.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : bst)
+ *this <<r.first <<r.second;
+ return *this;
+ }
+ //¶Ô¶àÖµ¶þ²æÊ÷¶Ô½øÐÐÎļþдÈë
+ template<typename Ty1, typename Ty2, typename TyComp>
+ BinWriteFile &operator <<(const std::multimap<Ty1, Ty2, TyComp> &bst)
+ {
+ //д³ß´ç
+ int64_t size = bst.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : bst)
+ *this <<r.first <<r.second;
+ return *this;
+ }
+ //¶Ô¹þÏ£±í½øÐÐÎļþдÈë
+ template<typename Ty, typename TyHash, typename TyComp>
+ BinWriteFile &operator <<(const std::unordered_set<Ty, TyHash, TyComp> &htb)
+ {
+ //д³ß´ç
+ int64_t size = htb.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : htb)
+ *this <<r;
+ return *this;
+ }
+ //¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþдÈë
+ template<typename Ty, typename TyHash, typename TyComp>
+ BinWriteFile &operator <<(const std::unordered_multiset<Ty, TyHash, TyComp> &htb)
+ {
+ //д³ß´ç
+ int64_t size = htb.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : htb)
+ *this <<r;
+ return *this;
+ }
+ //¶Ô¹þÏ£±í¶Ô½øÐÐÎļþдÈë
+ template<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
+ BinWriteFile &operator <<(const std::unordered_map<Ty1, Ty2, TyHash, TyComp> &htb)
+ {
+ //д³ß´ç
+ int64_t size = htb.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : htb)
+ *this <<r.first <<r.second;
+ return *this;
+ }
+ //¶Ô¶àÖµ¹þÏ£±í¶Ô½øÐÐÎļþдÈë
+ template<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
+ BinWriteFile &operator <<(const std::unordered_multimap<Ty1, Ty2, TyHash, TyComp> &htb)
+ {
+ //д³ß´ç
+ int64_t size = htb.size();
+ operator <<(size);
+ //дÊý¾Ý
+ for(auto &r : htb)
+ *this <<r.first <<r.second;
+ return *this;
+ }
+};
+
+//дÀàÐͶþ½øÖÆÎļþÀàµü´úÆ÷
+//ÊÇÊä³öµü´úÆ÷
+template<typename Ty>
+class BinWriteFileIter:
+ public std::iterator<std::output_iterator_tag, void,
+ void, void, void>
+{
+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 <<data;
+ return *this;
+ }
+};
+
+
+template<typename Ty>
+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<typename Ty, typename= typename std::enable_if<
+ IsRemoveCVRefSameSzOrString<Ty>::value>::type
+ > explicit BinReadFile(Ty &&name, bool o_bFast= false, bool o_bSave= false):
+ bFast(o_bFast), bSave(o_bSave)
+ {
+ Open(std::forward<Ty>(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<char *>(buf), size);
+ if(ifs.bad())
+ throw std::runtime_error("Read File Bad Error");
+ return *this;
+ }
+ //¶ÔÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
+ template<typename Ty>
+ typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile &
+ >::Type ReadArray(Ty *pt, size_t count)
+ {
+ ReadBuf(pt, sizeof(Ty)*count);
+ return *this;
+ }
+ //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐжÁÈ¡
+ template<typename Ty>
+ typename std::enable_if<!std::is_scalar<Ty>::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 Ty>
+ typename std::enable_if<std::is_scalar<
+ typename std::remove_all_extents<Ty>::type>::value, BinReadFile &
+ >::type operator >>(Ty &r)
+ {
+ ReadBuf(&r, sizeof(r));
+ return *this;
+ }
+ //¶Ô·ÇÄÚÖÃÀàÐÍÊý×é½øÐÐÎļþ¶ÁÈ¡
+ template<typename Ty, size_t N>
+ typename std::enable_if<!std::is_scalar<
+ typename std::remove_all_extents<Ty>::type>::value, BinReadFile &
+ >::type operator >>(Ty (&arrStr)[N])
+ {
+ for(int64_t i=0; i<N; ++i) {
+ if(ifs.fail())
+ return *this;
+ *this >>arrStr[i];
+ }
+ return *this;
+ }
+ //¶Ôpair½øÐÐÎļþ¶ÁÈ¡
+ template<typename Ty1, typename Ty2>
+ BinReadFile &operator >>(std::pair<Ty1, Ty2> &pr)
+ {
+ *this >>pr.first >>pr.second;
+ return *this;
+ }
+ //¶Ôtuple½øÐÐÎļþ¶ÁÈ¡
+ template<typename ...Tys>
+ BinReadFile &operator >>(std::tuple<Tys...> &tup)
+ {
+ TupleRead<sizeof...(Tys)-1>(tup);
+ return *this;
+ }
+ template<int index, typename ...Tys>
+ typename std::enable_if<(index>=0), void
+ >::type TupleRead(std::tuple<Tys...> &tup)
+ {
+ *this >>std::get<index>(tup);
+ TupleRead<index-1>(tup);
+ }
+ template<int index, typename Ty>
+ void TupleRead(Ty &tup)
+ {
+ }
+ //¶Ôstring½øÐÐÎļþ¶ÁÈ¡
+ template<typename Ty>
+ BinReadFile &operator >>(std::basic_string<Ty> &str)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ str.clear();
+ //¶ÁÊý¾Ý
+ if(bFast) {
+ if(bSave)
+ str.reserve((typename std::basic_string<Ty>::size_type)size);
+ str.resize((typename std::basic_string<Ty>::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<perBufSize? size:perBufSize;
+ auto nowSize = str.size();
+ str.resize((typename std::basic_string<Ty>::size_type)(nowSize+realSize));
+ ReadBuf(&str[0]+nowSize, (size_t)(realSize*sizeof(Ty)));
+ }
+ }
+ return *this;
+ }
+ //¶ÔvectorÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡
+ template<typename Ty>
+ typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile &
+ >::type operator >>(std::vector<Ty> &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<Ty>::size_type)size);
+ vec.resize((typename std::vector<Ty>::size_type)size);
+ ReadBuf(vec.data(), size*sizeof(Ty));
+ }
+ else {
+ for(; size>0; size-=perBufSize) {
+ if(ifs.fail())
+ return *this;
+ int64_t realSize = size<perBufSize? size:perBufSize;
+ auto nowSize = vec.size();
+ vec.resize((typename std::vector<Ty>::size_type)(nowSize+realSize));
+ ReadBuf(vec.data()+nowSize, realSize*sizeof(Ty));
+ }
+ }
+ return *this;
+ }
+ //¶Ôvector·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý
+ template<typename Ty>
+ typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile &
+ >::type operator >>(std::vector<Ty> &vec)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ //¶ÁÊý¾Ý
+ vec.clear();
+ if(bFast) {
+ if(bSave)
+ vec.reserve((typename std::vector<Ty>::size_type)size);
+ vec.resize((typename std::vector<Ty>::size_type)size);
+ for(auto &r : vec) {
+ if(ifs.fail())
+ return *this;
+ *this >>r;
+ }
+ }
+ else {
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ vec.emplace_back();
+ *this >>vec.back();
+ }
+ }
+ return *this;
+ }
+ //¶ÔarrayÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡
+ template<typename Ty, size_t c_size>
+ typename std::enable_if<std::is_scalar<Ty>::value, BinReadFile &
+ >::type operator >>(std::array<Ty, c_size> &arr)
+ {
+ //¶ÁÊý¾Ý
+ ReadBuf(arr.data(), c_size*sizeof(Ty));
+ return *this;
+ }
+ //¶Ôarray·ÇÄÚÖÃÀàÐͽøÐÐÎļþ¶ÁÈ¡
+ template<typename Ty, size_t c_size>
+ typename std::enable_if<!std::is_scalar<Ty>::value, BinReadFile &
+ >::type operator >>(std::array<Ty, c_size> &arr)
+ {
+ //¶ÁÊý¾Ý
+ for(auto &ele: arr) {
+ if(ifs.fail())
+ return *this;
+ *this >>ele;
+ }
+ return *this;
+ }
+ //¶Ôdeque½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý
+ template<typename Ty>
+ BinReadFile &operator >>(std::deque<Ty> &deq)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ deq.clear();
+ //¶ÁÊý¾Ý
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ deq.emplace_back();
+ *this >>deq.back();
+ }
+ return *this;
+ }
+ //¶Ôlist½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹Ô캯Êý
+ template<typename Ty>
+ BinReadFile &operator >>(std::list<Ty> &lis)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ lis.clear();
+ //¶ÁÊý¾Ý
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ lis.emplace_back();
+ *this >>lis.back();
+ }
+ return *this;
+ }
+ //¶Ô¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
+ template<typename Ty, typename TyComp>
+ BinReadFile &operator >>(std::set<Ty, TyComp> &bst)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ bst.clear();
+ //¶ÁÊý¾Ý
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty data;
+ *this >>data;
+ bst.insert(bst.end(), std::move(data));
+ }
+ return *this;
+ }
+ //¶Ô¶àÖµ¶þ²æÊ÷½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
+ template<typename Ty, typename TyComp>
+ BinReadFile &operator >>(std::multiset<Ty, TyComp> &bst)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ bst.clear();
+ //¶ÁÊý¾Ý
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty data;
+ *this >>data;
+ bst.insert(bst.end(), std::move(data));
+ }
+ return *this;
+ }
+ //¶Ô¶þ²æÊ÷¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
+ template<typename Ty1, typename Ty2, typename TyComp>
+ BinReadFile &operator >>(std::map<Ty1, Ty2, TyComp> &bst)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ bst.clear();
+ //¶ÁÊý¾Ý
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty1 data;
+ *this >>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<typename Ty1, typename Ty2, typename TyComp>
+ BinReadFile &operator >>(std::multimap<Ty1, Ty2, TyComp> &bst)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ bst.clear();
+ //¶ÁÊý¾Ý
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty1 data;
+ *this >>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<typename Ty, typename TyHash, typename TyComp>
+ BinReadFile &operator >>(std::unordered_set<Ty, TyHash, TyComp> &htb)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ htb.clear();
+ //¶ÁÊý¾Ý
+ if(bFast)
+ htb.reserve((typename std::unordered_set<Ty, TyHash, TyComp>::size_type)size);
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty data;
+ *this >>data;
+ htb.insert(std::move(data));
+ }
+ return *this;
+ }
+ //¶Ô¶àÖµ¹þÏ£±í½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
+ template<typename Ty, typename TyHash, typename TyComp>
+ BinReadFile &operator >>(std::unordered_multiset<Ty, TyHash, TyComp> &htb)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ htb.clear();
+ //¶ÁÊý¾Ý
+ if(bFast)
+ htb.reserve((typename std::unordered_multiset<Ty, TyHash, TyComp>::size_type)size);
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty data;
+ *this >>data;
+ htb.insert(std::move(data));
+ }
+ return *this;
+ }
+ //¶Ô¹þÏ£±í¶Ô½øÐÐÎļþ¶ÁÈ¡£¬ÐèĬÈϹ¹ÔìºÍÒÆ¶¯¸³Öµ
+ template<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
+ BinReadFile &operator >>(std::unordered_map<Ty1, Ty2, TyHash, TyComp> &htb)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ htb.clear();
+ //¶ÁÊý¾Ý
+ if(bFast)
+ htb.reserve((typename std::unordered_map<Ty1, Ty2, TyHash, TyComp>::size_type)size);
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty1 data;
+ *this >>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<typename Ty1, typename Ty2, typename TyHash, typename TyComp>
+ BinReadFile &operator >>(std::unordered_multimap<Ty1, Ty2, TyHash, TyComp> &htb)
+ {
+ //¶Á³ß´ç
+ int64_t size = -1;
+ operator >>(size);
+ if(ifs.fail())
+ return *this;
+ htb.clear();
+ //¶ÁÊý¾Ý
+ if(bFast)
+ htb.reserve((typename std::unordered_multimap<Ty1, Ty2, TyHash, TyComp>::size_type)size);
+ for(int64_t i=0; i<size; ++i) {
+ if(ifs.fail())
+ return *this;
+ Ty1 data;
+ *this >>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<typename Ty>
+class BinReadFileIter:
+ public std::iterator<std::input_iterator_tag, Ty,
+ int64_t, Ty *, Ty &>
+{
+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 <cstddef>
+#include <cmath>
+#include <cassert>
+
+#include <type_traits>
+#include <limits>
+#include <algorithm>
+#include <initializer_list>
+#include <utility>
+#include <tuple>
+#include <functional>
+#include <iterator>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+#include <unordered_map>
+
+#include <stdexcept>
+#include <random>
+#include <ratio>
+
+
+//¿â¹ØÁªÐèÇóÎļþ
+#include "TypeExtend.h"
+
+
+
+//ÆäËû¿âÎļþÉùÃ÷
+
+//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐÍ£¬Ê¹ÓôøcvrefµÄÀàÐÍ´«Èë
+template<typename TyFunc, typename TyTup>
+struct TupleInvokeReturnType;
+
+//tupleÀàÐ͵÷Óú¯Êý£¬±¾ÖÊÉÏÖ»ÒªÄܱ»getº¯Êý²ð½â¼´¿É£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë
+template<typename TyFunc, typename TyTup>
+inline typename TupleInvokeReturnType<TyFunc &&, TyTup &&
+>::type TupleInvoke(TyFunc &&func, TyTup &&tup);
+
+//дÀàÐͶþ½øÖÆÎļþÀà
+//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿
+class BinWriteFile;
+
+//¶ÁÀàÐͶþ½øÖÆÎļþÀà
+//²»Í¬»·¾³µÄÄÚÖÃÀàÐÍ´óС²»Ò»¶¨Ïàͬ£¬Òª±£Ö¤Ê¹ÓôóСÎ޹رäÁ¿
+class BinReadFile;
+
+
+
+
+//¿ìËÙ¼ÆËãÃݴΣ¬×¢Òâ·µ»ØÀàÐͺͻùÀàÐÍÏàͬ
+template<typename Ty>
+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<typename Ratio, typename BaseRatio,
+ typename CompareRatio =std::ratio<1>
+> inline constexpr typename std::enable_if<
+ std::ratio_greater_equal<Ratio, CompareRatio>::value, int
+>::type RatioPrecision()
+{
+ return 0;
+}
+template<typename Ratio, typename BaseRatio,
+ typename CompareRatio =std::ratio<1>
+> inline constexpr typename std::enable_if<
+ !std::ratio_greater_equal<Ratio, CompareRatio>::value, int
+>::type RatioPrecision()
+{
+ return RatioPrecision<std::ratio_multiply<Ratio, BaseRatio>,
+ BaseRatio, CompareRatio>()+1;
+}
+
+
+
+//Éú³ÉºóÒ»¸ö×éºÏÊý£¬·µ»ØÊÇ·ñµ½Í·
+//ÒªÇóË«Ïòµü´úÆ÷£¬¿ÉµÝÔö¡¢ÏàµÈ±È½ÏÖµÀàÐÍ
+template<typename TyIt, typename Ty>
+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<typename TyIt, typename Ty>
+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<typename TyIt1, typename TyIt2,
+ typename TyLess= GeneralLess<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::type>,
+ typename TyEqual= GeneralEqualTo<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::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<typename TyIt1, typename TyIt2,
+ typename TyLess= GeneralLess<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::type>,
+ typename TyEqual= GeneralEqualTo<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::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<typename TyIt1, typename TyIt2,
+ typename TyLess= GeneralLess<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::type>,
+ typename TyEqual= GeneralEqualTo<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::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<typename TyIt1, typename TyIt2,
+ typename TyLess= GeneralLess<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::type>,
+ typename TyEqual= GeneralEqualTo<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::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<typename TyData= void>
+class IndexDisjointSet
+{
+private:
+ //²¢²é¼¯½ÚµãÊý¾Ý½á¹¹
+ struct Node:
+ public ValueHolder<TyData>
+ {
+ size_t idxPr;//¸¸Ö¸Õë
+ size_t rank = 0;//ÖÈ£¬Ëã·¨ÓÃ
+ template<typename ...Ty_S>
+ Node(size_t idx, Ty_S &&...arg_s):
+ ValueHolder<TyData>(std::forward<Ty_S>(arg_s)...), idxPr(idx)
+ {
+ }
+ };
+
+private:
+ std::vector<Node> vec;//Êý¾Ý
+
+public:
+ //¹¹Ô캯Êý
+ IndexDisjointSet()
+ = default;
+ IndexDisjointSet(const IndexDisjointSet &)
+ = default;
+ IndexDisjointSet &operator =(const IndexDisjointSet &)
+ = default;
+ IndexDisjointSet(IndexDisjointSet &&)
+ = default;
+ IndexDisjointSet &operator =(IndexDisjointSet &&)
+ = default;
+ //¶àÊý¾Ý¹¹Ôì
+ template<typename ...Ty_S>
+ explicit IndexDisjointSet(size_t size, Ty_S &&...arg_s)
+ {
+ Assign(size, std::forward<Ty_S>(arg_s)...);
+ }
+public:
+ //¶àÊý¾Ý¸³Öµ
+ template<typename ...Ty_S>
+ IndexDisjointSet &Assign(size_t size, Ty_S &&...arg_s)
+ {
+ for(size_t i=0; i!=size; ++i)
+ Emplace(std::forward<Ty_S>(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<typename ...Ty_S>
+ size_t Emplace(Ty_S &&...arg_s)
+ {
+ size_t root = vec.size();
+ vec.emplace_back(root, std::forward<Ty_S>(arg_s)...);
+ return root;
+ }
+ //Ìí¼ÓµãͬʱÁ¬½Ó£¬·µ»Ø¸ù
+ template<typename ...Ty_S>
+ size_t EmplaceUnion(size_t idx, Ty_S &&...arg_s)
+ {
+ size_t root = vec.size();
+ vec.emplace_back(root, std::forward<Ty_S>(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<typename TyKey, typename TyValue= void, typename TyCom= std::less<TyKey>>
+class MapDisjointSetNode;
+//Ê÷Ðβ¢²é¼¯ÀàÐͼòд£¬Ö§³ÖÁ¬½ÓºÍÌí¼Ó»ìÓ㬲¢²é¼¯±êǩΪÊ÷µü´úÆ÷
+template<typename TyKey, typename TyValue= void, typename TyCom= std::less<TyKey>>
+using MapDisjointSet = std::map<TyKey, MapDisjointSetNode<TyKey, TyValue, TyCom>, TyCom>;
+//Ê÷Ðβ¢²é¼¯£¬½Úµã½á¹¹£¬½«Æä¸³¸ømapÄ£°åÀàÐÍʹÓÃ
+template<typename TyKey, typename TyValue, typename TyCom>
+class MapDisjointSetNode:
+ private ValueHolder<TyValue>
+{
+ template<typename TyIt>
+ friend TyIt MapDisjointSetFindRoot(TyIt it);
+ template<typename TyIt>
+ friend TyIt MapDisjointSetUnion(TyIt it1, TyIt it2);
+private:
+ typename MapDisjointSet<TyKey, TyValue, TyCom>::iterator itPr;//´æ´¢Ö¸Õë
+ size_t rank = 0;//ÖÈ£¬Ëã·¨ÓÃ
+ bool bRoot = true;//¼Ç¼ÊÇ·ñΪ¸ù£¬Îª¸ùʱ²»Ðè±£Ö¤Ö¸ÕëÓÐЧ
+public:
+ //¹¹Ô캯Êý
+ template<typename ...Ty_S>
+ MapDisjointSetNode(Ty_S &&...arg_s):
+ ValueHolder<TyValue>(std::forward<Ty_S>(arg_s)...)
+ {
+ }
+ //ÒýÓÃԭʼÊý¾Ý
+ typename ValueHolder<TyValue>::RefType Get()
+ {
+ return this->hold;
+ }
+ typename ValueHolder<TyValue>::ConstRefType Get() const
+ {
+ return this->hold;
+ }
+};
+//Ê÷Ðβ¢²é¼¯¾²Ì¬Ëã·¨£¬ÕÒ¸ù½Úµã£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷
+template<typename TyIt>
+inline TyIt MapDisjointSetFindRoot(TyIt it)
+{
+ if(it->second.bRoot)
+ return it;
+ else {
+ it->second.itPr = MapDisjointSetFindRoot(it->second.itPr);
+ return it->second.itPr;
+ }
+}
+//Ê÷Ðβ¢²é¼¯¾²Ì¬Ëã·¨£¬ºÏ²¢¼¯ºÏ£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷£¬·µ»Ø¸ù
+template<typename TyIt>
+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 TyKey, typename TyValue= void,
+ typename TyHash= std::hash<TyKey>, typename TyEqual= std::equal_to<TyKey>
+> class UnordMapDisjointSetNode;
+//¹þÏ£²¢²é¼¯ÀàÐͼòд£¬Ö§³ÖÁ¬½ÓºÍÌí¼Ó»ìÓ㬲¢²é¼¯±êǩΪÄÚÈÝpairÖ¸Õë
+template<typename TyKey, typename TyValue= void,
+ typename TyHash= std::hash<TyKey>, typename TyEqual= std::equal_to<TyKey>
+> using UnordMapDisjointSet = std::unordered_map<TyKey,
+ UnordMapDisjointSetNode<TyKey, TyValue, TyHash, TyEqual>, TyHash, TyEqual>;
+//¹þÏ£²¢²é¼¯£¬½Úµã½á¹¹£¬½«Æä¸³¸øunordered_mapÄ£°åÀàÐÍʹÓÃ
+template<typename TyKey, typename TyValue, typename TyHash, typename TyEqual>
+class UnordMapDisjointSetNode:
+ private ValueHolder<TyValue>
+{
+ template<typename TyIt>
+ friend auto UnordMapDisjointSetFindRoot(TyIt it)-> decltype(&*it);
+ template<typename TyIt>
+ friend auto UnordMapDisjointSetUnion(TyIt it1, TyIt it2)-> decltype(&*it1);
+private:
+ typename UnordMapDisjointSet<TyKey, TyValue, TyHash, TyEqual>::pointer pPr= nullptr;//´æ´¢Ö¸Õë
+ size_t rank = 0;//ÖÈ£¬Ëã·¨ÓÃ
+ bool bRoot = true;//¼Ç¼ÊÇ·ñΪ¸ù£¬Îª¸ùʱ²»Ðè±£Ö¤Ö¸ÕëÓÐЧ
+public:
+ //¹¹Ô캯Êý
+ template<typename ...Ty_S>
+ UnordMapDisjointSetNode(Ty_S &&...arg_s):
+ ValueHolder<TyValue>(std::forward<Ty_S>(arg_s)...)
+ {
+ }
+ //ÒýÓÃԭʼÊý¾Ý
+ typename ValueHolder<TyValue>::RefType Get()
+ {
+ return this->hold;
+ }
+ typename ValueHolder<TyValue>::ConstRefType Get() const
+ {
+ return this->hold;
+ }
+};
+//¹þÏ£²¢²é¼¯¾²Ì¬Ëã·¨£¬ÕÒ¸ù½Úµã£¬½ÓÊÜÖ¸Õë»òµü´úÆ÷
+template<typename TyIt>
+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<typename TyIt>
+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<typename TyMatch, typename TyData>
+struct _TrieTreeNode
+{
+ using RetDataType = TyData *;
+ using ConstRetDataType = const TyData *;
+ constexpr static bool bIsVoid = false;
+public:
+ TyData *pData = nullptr;
+ std::map<TyMatch, _TrieTreeNode<TyMatch, TyData>> 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<typename ...Ty_S>
+ void Construct(Ty_S &&...arg_s)
+ {
+ assert(pData==nullptr);
+ pData = new TyData(std::forward<Ty_S>(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<typename TyMatch>
+struct _TrieTreeNode<TyMatch, void>
+{
+ using RetDataType = bool;
+ using ConstRetDataType = bool;
+ constexpr static bool bIsVoid = true;
+public:
+ bool bData = false;//ÊÇ·ñÓÐÊý¾Ý
+ std::map<TyMatch, _TrieTreeNode<TyMatch, void>> 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<typename TyMatch, typename TyData>
+struct _UnordTrieTreeNode
+{
+ using RetDataType = TyData *;
+ using ConstRetDataType = const TyData *;
+ constexpr static bool bIsVoid = false;
+public:
+ TyData *pData = nullptr;
+ std::unordered_map<TyMatch, _UnordTrieTreeNode<TyMatch, TyData>> 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<typename ...Ty_S>
+ void Construct(Ty_S &&...arg_s)
+ {
+ assert(pData==nullptr);
+ pData = new TyData(std::forward<Ty_S>(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<typename TyMatch>
+struct _UnordTrieTreeNode<TyMatch, void>
+{
+ using RetDataType = bool;
+ using ConstRetDataType = bool;
+ constexpr static bool bIsVoid = true;
+public:
+ bool bData = false;//ÊÇ·ñÓÐÊý¾Ý
+ std::unordered_map<TyMatch, _UnordTrieTreeNode<TyMatch, void>> 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<typename TyNode>
+inline typename std::enable_if<!TyNode::bIsVoid, void
+>::type _BinWriteTrieOrAcNodeAssist(BinWriteFile &bwf, TyNode &node)
+{
+ uint8_t bData = node.pData!=nullptr;
+ bwf <<bData;
+ if(bData)
+ bwf <<*node.pData;
+ bwf <<node.mapCh;
+}
+template<typename TyNode>
+inline typename std::enable_if<TyNode::bIsVoid, void
+>::type _BinWriteTrieOrAcNodeAssist(BinWriteFile &bwf, TyNode &node)
+{
+ bwf <<(uint8_t)node.bData;
+ bwf <<node.mapCh;
+}
+template<typename TyNode>
+inline typename std::enable_if<!TyNode::bIsVoid, void
+>::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<typename TyNode>
+inline typename std::enable_if<TyNode::bIsVoid, void
+>::type _BinReadTrieOrAcNodeAssist(BinReadFile &brf, TyNode &node)
+{
+ uint8_t bData;
+ brf >>bData;
+ node.bData = bData;
+ brf >>node.mapCh;
+}
+
+//binfile½Ó¿Ú
+template<typename TyMatch, typename TyData>
+inline BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeNode<TyMatch, TyData> &node)
+{
+ _BinWriteTrieOrAcNodeAssist(bwf, node);
+ return bwf;
+}
+template<typename TyMatch, typename TyData>
+inline BinReadFile &operator >>(BinReadFile &brf, _TrieTreeNode<TyMatch, TyData> &node)
+{
+ _BinReadTrieOrAcNodeAssist(brf, node);
+ return brf;
+}
+template<typename TyMatch, typename TyData>
+inline BinWriteFile &operator <<(BinWriteFile &bwf, const _UnordTrieTreeNode<TyMatch, TyData> &node)
+{
+ _BinWriteTrieOrAcNodeAssist(bwf, node);
+ return bwf;
+}
+template<typename TyMatch, typename TyData>
+inline BinReadFile &operator >>(BinReadFile &brf, _UnordTrieTreeNode<TyMatch, TyData> &node)
+{
+ _BinReadTrieOrAcNodeAssist(brf, node);
+ return brf;
+}
+
+template<typename TyNode>
+class _TrieTreeTemplate;
+//Ê÷ÐÎÆ¥Åä½á¹¹ÉÏÏÂÎÄ
+template<typename TyNode, typename TyIt>
+struct _TrieContextTemplate
+{
+ bool bFirst = true;//¼Ç¼Ê×´ÎÆ¥Åä
+ TyNode *pt;//Ê÷½ÚµãÖ¸Õë
+ TyIt it;//Æ¥Åä´®Ö¸Õë
+};
+template<typename TyNode, typename TyIt>
+inline _TrieContextTemplate<TyNode, TyIt> MakeTrieContext(const _TrieTreeTemplate<TyNode> &, TyIt)
+{
+ return _TrieContextTemplate<TyNode, TyIt>();
+}
+
+//Ê÷×´´®Æ¥Åä½á¹¹£¬Ö§³ÖvoidÊý¾Ý
+template<typename TyNode>
+class _TrieTreeTemplate
+{
+ template<typename TyNode2>
+ friend BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeTemplate<TyNode2> &trie);
+ template<typename TyNode2>
+ friend BinReadFile &operator >>(BinReadFile &brf, _TrieTreeTemplate<TyNode2> &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<typename TyIt>
+ 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<typename TyIt, typename ...Ty_S>
+ 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<Ty_S>(arg_s)...);
+ return true;
+ }
+ //Çå³ý½Úµã
+ void Clear()
+ {
+ pRoot->Clear();
+ }
+ //Æ¥ÅäÍêÕû´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û
+ //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õë»ò·ñ£¬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖÃ
+ template<typename TyIt>
+ std::pair<TyIt, RetDataType> Match(TyIt itSt, TyIt itEd)
+ {
+ NodeType *pNode = pRoot;
+ FindAssist(pNode, itSt, itEd, false, true, false);
+ return std::make_pair(itSt, NodeType::GetData(pNode));
+ }
+ template<typename TyIt>
+ std::pair<TyIt, ConstRetDataType> Match(TyIt itSt, TyIt itEd) const
+ {
+ return ((_TrieTreeTemplate *)this)->Match(itSt, itEd);
+ }
+ //µü´úËÑË÷´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û
+ //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖÃ
+ //ctx³õʼ¸³Ä¬ÈϹ¹Ô죬֮ºóÁ¬ÐøÊ¹ÓôË×÷ΪÖмä¼þ
+ template<typename TyIt, typename TyCtx= _TrieContextTemplate<TyNode, TyIt>>
+ typename std::enable_if<IsRemoveCVRefSame<_TrieContextTemplate<TyNode, TyIt>,
+ TyCtx>::value, std::pair<TyIt, RetDataType>
+ >::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 TyIt, typename TyCtx= _TrieContextTemplate<TyNode, TyIt>>
+ typename std::enable_if<IsRemoveCVRefSame<_TrieContextTemplate<TyNode, TyIt>,
+ TyCtx>::value, std::pair<TyIt, ConstRetDataType>
+ >::type Search(TyIt itSt, TyIt itEd, TyCtx &&ctx= TyCtx()) const
+ {
+ return ((_TrieTreeTemplate *)this)->Search(itSt, itEd, ctx);
+ }
+ //Æ¥Åä×´®£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û
+ //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½Ôòµü´úÆ÷Ϊβºó£¬ÈôδÕÒµ½µü´úÆ÷´æÆ¥Åä²»µ½µÄµÚÒ»¸öλÖÃ
+ template<typename TyIt>
+ std::pair<TyIt, RetDataType> SearchLong(TyIt itSt, TyIt itEd)
+ {
+ _TrieContextTemplate<TyNode, TyIt> 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<typename TyIt>
+ std::pair<TyIt, ConstRetDataType> SearchLong(TyIt itSt, TyIt itEd) const
+ {
+ return ((_TrieTreeTemplate *)this)->SearchLong(itSt, itEd);
+ }
+ //ÕÒµ½µÚÒ»¸ö
+ template<typename TyIt>
+ RetDataType Judge(TyIt itSt, TyIt itEd)
+ {
+ return Search(itSt, itEd).second;
+ }
+ template<typename TyIt>
+ ConstRetDataType Judge(TyIt itSt, TyIt itEd) const
+ {
+ return ((_TrieTreeTemplate *)this)->Judge(itSt, itEd);
+ }
+ //¼ÆÊýÕÒµ½´ÎÊý
+ template<typename TyIt>
+ size_t Count(TyIt itSt, TyIt itEd) const
+ {
+ _TrieContextTemplate<TyNode, TyIt> ctx;
+ size_t cnt = 0;
+ for(; ; ++cnt) {
+ if(!Search(itSt, itEd, ctx).second)
+ break;
+ }
+ return cnt;
+ }
+};
+
+//binfile½Ó¿Ú
+template<typename TyNode>
+inline BinWriteFile &operator <<(BinWriteFile &bwf, const _TrieTreeTemplate<TyNode> &trie)
+{
+ return bwf <<*trie.pRoot;
+}
+template<typename TyNode>
+inline BinReadFile &operator >>(BinReadFile &brf, _TrieTreeTemplate<TyNode> &trie)
+{
+ return brf >>*trie.pRoot;
+}
+
+//¶¨ÒåËÑË÷Ê÷µÄƽºâÊ÷ʵÏÖ
+template<typename TyMatch, typename TyData= void>
+using TrieTree = _TrieTreeTemplate<_TrieTreeNode<TyMatch, TyData>>;
+template<typename TyMatch, typename TyData, typename TyIt>
+using TrieContext = _TrieContextTemplate<_TrieTreeNode<TyMatch, TyData>, TyIt>;
+//¶¨ÒåËÑË÷Ê÷µÄ¹þÏ£±íʵÏÖ
+template<typename TyMatch, typename TyData= void>
+using UnordTrieTree = _TrieTreeTemplate<_UnordTrieTreeNode<TyMatch, TyData>>;
+template<typename TyMatch, typename TyData, typename TyIt>
+using UnordTrieContext = _TrieContextTemplate<_UnordTrieTreeNode<TyMatch, TyData>, TyIt>;
+
+
+
+//KMPËÑË÷ÀàÉÏÏÂÎÄ
+template<typename TyItT, typename TyItP>
+struct KmpContext
+{
+ ptrdiff_t cnt = -1;//ÒÑÆ¥ÅäµÄ¸öÊý£¬¸ºÊý±íʾδ³õʼ»¯
+ TyItP itSub;//Æ¥Åäģʽ´®µÄµü´úλÖÃ
+ TyItT it;//Îı¾´®Î»ÖÃ
+ TyItT itTFlag;//Îı¾´®¶ÔÆë¿ªÊ¼Î»ÖÃ
+};
+template<typename TyItT, typename TyItP>
+inline KmpContext<TyItT, TyItP> MakeKmpContext(TyItT, TyItP)
+{
+ return KmpContext<TyItT, TyItP>();
+}
+
+//KMPËÑË÷Àà
+class KmpSearcher
+{
+ std::vector<ptrdiff_t> vecSub;//¼Ç¼ÓÒÒÆµÄ³¤¶È£¬µÚiÏî¼Ç¼µÄÊÇÒÑÆ¥Åäi+1¸öºóµÄÒÆ¶¯³¤¶È£¬¼´Ï±êiλÖÃ
+public:
+ KmpSearcher()
+ = default;
+ template<typename TyIt>
+ KmpSearcher(TyIt itSt, TyIt itEd)
+ {
+ Assign(itSt, itEd);
+ }
+public:
+ //¸³Öµº¯Êý
+ template<typename TyIt>
+ 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 TyItT, typename TyItP, typename TyCtx= KmpContext<TyItT, TyItP>>
+ typename std::enable_if<IsRemoveCVRefSame<KmpContext<TyItT, TyItP>, TyCtx>::value,
+ std::pair<TyItT, TyItT>
+ >::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<typename TyItT, typename TyItP>
+ bool Judge(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd) const
+ {
+ return Search(itTSt, itTEd, itPSt, itPEd).first!=itTEd;
+ }
+ //¼ÆÊýÕÒµ½´ÎÊý
+ template<typename TyItT, typename TyItP>
+ size_t Conut(TyItT itTSt, TyItT itTEd, TyItP itPSt, TyItP itPEd) const
+ {
+ KmpContext<TyItT, TyItP> ctx;
+ size_t cnt = 0;
+ for(; ; ++cnt) {
+ if(Search(itTSt, itTEd, itPSt, itPEd, ctx).first==itTEd)
+ break;
+ }
+ return cnt;
+ }
+};
+
+
+
+//AC×Ô¶¯»úÄÚ²¿½ÚµãÀàÐÍ£¬Æ½ºâÊ÷ʵÏÖ
+template<typename TyMatch, typename TyData>
+struct _AcMachineNode
+{
+ using RetDataType = TyData *;
+ using ConstRetDataType = const TyData *;
+ constexpr static bool bIsVoid = false;
+public:
+ TyData *pData = nullptr;
+ std::map<TyMatch, _AcMachineNode> 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<typename ...Ty_S>
+ void Construct(Ty_S &&...arg_s)
+ {
+ assert(pData==nullptr);
+ pData = new TyData(std::forward<Ty_S>(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<typename TyMatch>
+struct _AcMachineNode<TyMatch, void>
+{
+ using RetDataType = bool;
+ using ConstRetDataType = bool;
+ constexpr static bool bIsVoid = true;
+public:
+ bool bData = false;//ÊÇ·ñÓÐÊý¾Ý
+ std::map<TyMatch, _AcMachineNode> 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<typename TyMatch, typename TyData>
+struct _UnordAcMachineNode
+{
+ using RetDataType = TyData *;
+ using ConstRetDataType = const TyData *;
+ constexpr static bool bIsVoid = false;
+public:
+ TyData *pData = nullptr;
+ std::unordered_map<TyMatch, _UnordAcMachineNode> 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<typename ...Ty_S>
+ void Construct(Ty_S &&...arg_s)
+ {
+ assert(pData==nullptr);
+ pData = new TyData(std::forward<Ty_S>(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<typename TyMatch>
+struct _UnordAcMachineNode<TyMatch, void>
+{
+ using RetDataType = bool;
+ using ConstRetDataType = bool;
+ constexpr static bool bIsVoid = true;
+public:
+ bool bData = false;//ÊÇ·ñÓÐÊý¾Ý
+ std::unordered_map<TyMatch, _UnordAcMachineNode> 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<typename TyMatch, typename TyData>
+inline BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineNode<TyMatch, TyData> &node)
+{
+ _BinWriteTrieOrAcNodeAssist(bwf, node);
+ return bwf;
+}
+template<typename TyMatch, typename TyData>
+inline BinReadFile &operator >>(BinReadFile &brf, _AcMachineNode<TyMatch, TyData> &node)
+{
+ _BinReadTrieOrAcNodeAssist(brf, node);
+ return brf;
+}
+template<typename TyMatch, typename TyData>
+inline BinWriteFile &operator <<(BinWriteFile &bwf, const _UnordAcMachineNode<TyMatch, TyData> &node)
+{
+ _BinWriteTrieOrAcNodeAssist(bwf, node);
+ return bwf;
+}
+template<typename TyMatch, typename TyData>
+inline BinReadFile &operator >>(BinReadFile &brf, _UnordAcMachineNode<TyMatch, TyData> &node)
+{
+ _BinReadTrieOrAcNodeAssist(brf, node);
+ return brf;
+}
+
+template<typename TyNode>
+class _AcMachineTemplate;
+//AC×Ô¶¯»úËÑË÷ÀàÉÏÏÂÎÄ
+template<typename TyNode, typename TyIt>
+struct _AcContextTemplate
+{
+ bool bFirst = true;//¼Ç¼Ê×´ÎÆ¥Åä
+ TyNode *pt = nullptr;//Ê÷½ÚµãÖ¸Õë
+ TyNode *pFind = nullptr;//ÕýÔÚ²éÕÒÖ¸Õë
+ TyIt it;//Æ¥Åä´®Ö¸Õë
+};
+template<typename TyNode, typename TyIt>
+inline _AcContextTemplate<TyNode, TyIt> MakeAcContext(const _AcMachineTemplate<TyNode> &, TyIt)
+{
+ return _AcContextTemplate<TyNode, TyIt>();
+}
+
+//AC×Ô¶¯»úËÑË÷À֧࣬³ÖvoidÊý¾Ý
+template<typename TyNode>
+class _AcMachineTemplate
+{
+ template<typename TyNode2>
+ friend BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineTemplate<TyNode2> &acm);
+ template<typename TyNode2>
+ friend BinReadFile &operator >>(BinReadFile &brf, _AcMachineTemplate<TyNode2> &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<NodeType *> 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<typename TyIt, typename ...Ty_S>
+ 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<Ty_S>(arg_s)...);
+ return true;
+ }
+ //Çå³ý½Úµã
+ void Clear()
+ {
+ pRoot->Clear();
+ bPrepare = true;
+ }
+ //µü´úËÑË÷º¯Êý£¬Êý¾ÝÀàÐÍ·µ»ØÖ¸Õ룬¿ÕÀàÐÍ·µ»Ø²¼¶û
+ //ÕÒ²»µ½·µ»Ø¿ÕÖ¸Õ룬ÈôÕÒµ½·µ»ØÕÒµ½Î²ºóºÍ³¤¶È£¬Î´ÕÒµ½·µ»Ø´®Î²ºóºÍ0
+ template<typename TyIt, typename TyCtx= _AcContextTemplate<TyNode, TyIt>>
+ typename std::enable_if<IsRemoveCVRefSame<_AcContextTemplate<TyNode, TyIt>, TyCtx>::value,
+ std::tuple<TyIt, size_t, RetDataType>
+ >::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<typename TyIt>
+ RetDataType Judge(TyIt itSt, TyIt itEd)
+ {
+ return std::get<2>(Search(itSt, itEd));
+ }
+ //¼ÆÊýÕÒµ½´ÎÊý
+ template<typename TyIt>
+ RetDataType Count(TyIt itSt, TyIt itEd)
+ {
+ _AcContextTemplate<TyNode, TyIt> ctx;
+ size_t cnt = 0;
+ for(; ; ++cnt) {
+ if(std::get<2>(Search(itSt, itEd, ctx)))
+ break;
+ }
+ return cnt;
+ }
+};
+
+//binfile½Ó¿Ú
+template<typename TyNode>
+inline BinWriteFile &operator <<(BinWriteFile &bwf, const _AcMachineTemplate<TyNode> &acm)
+{
+ return bwf <<(uint8_t)acm.bPrepare
+ <<*acm.pRoot;
+}
+template<typename TyNode>
+inline BinReadFile &operator >>(BinReadFile &brf, _AcMachineTemplate<TyNode> &acm)
+{
+ uint8_t bPrepare;
+ brf >>bPrepare;
+ acm.bPrepare = false;
+ brf >>*acm.pRoot;
+ if(bPrepare)
+ acm.Prepare();
+ return brf;
+}
+
+//¶¨ÒåËÑË÷Ê÷µÄƽºâÊ÷ʵÏÖ
+template<typename TyMatch, typename TyData= void>
+using AcMachine = _AcMachineTemplate<_AcMachineNode<TyMatch, TyData>>;
+template<typename TyMatch, typename TyData, typename TyIt>
+using AcContext = _AcContextTemplate<_AcMachineNode<TyMatch, TyData>, TyIt>;
+//¶¨ÒåËÑË÷Ê÷µÄ¹þÏ£±íʵÏÖ
+template<typename TyMatch, typename TyData= void>
+using UnordAcMachine = _AcMachineTemplate<_UnordAcMachineNode<TyMatch, TyData>>;
+template<typename TyMatch, typename TyData, typename TyIt>
+using UnordAcContext = _AcContextTemplate<_UnordAcMachineNode<TyMatch, TyData>, TyIt>;
+
+
+
+
+//Ö»ÄÜÌí¼ÓÔªËØµÄͼ£¬Ö§³ÖvoidÊý¾ÝÀàÐÍ
+//ÄÚ²¿Îª¶þάÊý×éʵÏÖ
+//½Úµãµü´úÆ÷ÔÊÐíʹÓÃÕûÐÎË÷Òý¹¹Ôì
+//ClearºÍAssign»áµ¼Öµü´úÆ÷ʧЧ
+//ÈÝÆ÷¸´ÖÆ¡¢Òƶ¯¡¢½»»»ºóµü´úÆ÷¾ùÖ¸Ïò¾ÉÈÝÆ÷£¬ÔÊÐíµü´úÆ÷¸üÐÂÈÝÆ÷Ö¸Õë
+//TODO: Ïë½á¹¹Éè¼Æ£¬³¢ÊÔ½«½ÚµãÓë±ß¶ÔÓ¦µ½ÕûÐÎË÷ÒýÉÏ
+template<typename TyNodeData, typename TyEdgeData>
+class AddonlyGraph
+{
+private:
+ //±ß½á¹¹Ìå
+ struct EdgeStruct:
+ public ValueHolder<TyEdgeData>
+ {
+ size_t index;//±ß±àºÅ
+ //½ÓÊÕÊý¾ÝÀàÐÍÄ£°å²ÎÊýµÄ¹¹Ôì
+ template<typename ...Tys>
+ EdgeStruct(size_t o_index, Tys &&...args):
+ ValueHolder<TyEdgeData>(std::forward<Tys>(args)...), index(o_index)
+ {
+ }
+ };
+ //½Úµã½á¹¹Ìå
+ struct NodeStruct:
+ public ValueHolder<TyNodeData>
+ {
+ std::vector<EdgeStruct> vecEdge;//³ö±ßÊý×é
+ //½ÓÊÕ×óÖµ»òÓÒÖµµÄÊý¾Ý¹¹Ôì
+ template<typename ...Tys>
+ NodeStruct(Tys &&...args):
+ ValueHolder<TyNodeData>(std::forward<Tys>(args)...)
+ {
+ }
+ };
+
+private://¸¨ÖúÀàÐͶ¨Òå
+ using GraphType = AddonlyGraph<TyNodeData, TyEdgeData>;//ͼÀàÐÍ
+public:
+ using NodeDataType = TyNodeData;//½ÚµãÊý¾ÝÀàÐÍ
+ using EdgeDataType = TyEdgeData;//±ßÊý¾ÝÀàÐÍ
+
+private://µü´úÆ÷Ä£°å¶¨Òå
+ //½Úµãµü´úÆ÷Ä£°å¸¨ÖúÀà
+ template<typename GraphTypeMy, typename TyNodeDataMy, typename TyNodeDataPure>
+ class TemplateNodeIterAssist;
+ //½Úµãµü´úÆ÷Ä£°å
+ template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy>
+ class TemplateNodeIter;
+ //±ßµü´úÆ÷Ä£°å¸¨ÖúÀà
+ template<typename GraphTypeMy, typename TyNodeDataMy, typename TyNodeDataPure>
+ class TemplateEdgeIterAssist;
+ //±ßµü´úÆ÷Ä£°å
+ template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy>
+ class TemplateEdgeIter;
+
+private://µü´úÆ÷Ä£°åÖ¸¶¨ÀàÐͶ¨Òå
+ //½Úµãµü´úÆ÷¸¨ÖúÀàÖ¸¶¨
+ using NodeIterAssist = TemplateNodeIter<GraphType, TyNodeData, TyNodeData>;
+ //½Úµã³£µü´úÆ÷¸¨ÖúÀàÖ¸¶¨
+ using NodeConstIterAssist = TemplateNodeIter<
+ const GraphType, const TyNodeData, TyNodeData>;
+ //±ßµü´úÆ÷¸¨ÖúÀàÖ¸¶¨
+ using EdgeIterAssist = TemplateEdgeIter<GraphType, TyEdgeData, TyEdgeData>;
+ //±ß³£µü´úÆ÷¸¨ÖúÀàÖ¸¶¨
+ using EdgeConstIterAssist = TemplateEdgeIter<
+ const GraphType, const TyEdgeData, TyEdgeData>;
+public:
+ //½Úµãµü´úÆ÷ÀàÖ¸¶¨
+ using NodeIter = TemplateNodeIter<GraphType, TyNodeData, TyEdgeData>;
+ //½Úµã³£µü´úÆ÷ÀàÖ¸¶¨
+ using NodeConstIter = TemplateNodeIter<
+ const GraphType, const TyNodeData, const TyEdgeData>;
+ //±ßµü´úÆ÷ÀàÖ¸¶¨
+ using EdgeIter = TemplateEdgeIter<GraphType, TyNodeData, TyEdgeData>;
+ //±ß³£µü´úÆ÷ÀàÖ¸¶¨
+ 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<NodeStruct> vecNode;//½ÚµãÊý×é
+
+public://»ù±¾º¯Êý
+ //ĬÈϹ¹Ôì
+ AddonlyGraph()
+ = default;
+ //¶à¸öÊý¾Ý¹¹Ôì
+ template<typename ...Ty_S>
+ explicit AddonlyGraph(size_t size, const Ty_S &...arg_s)
+ {
+ Assign(size, arg_s...);
+ }
+public://³ÉÔ±º¯Êý
+ //¸³Öµº¯Êý
+ template<typename ...Ty_S>
+ AddonlyGraph &Assign(size_t size, const Ty_S &...arg_s)
+ {
+ vecNode.assign(size, NodeStruct(arg_s...));
+ return *this;
+ }
+ //Ìí¼Ó½Úµã
+ template<typename TyNodeDataMy>
+ typename std::enable_if<std::is_convertible<TyNodeDataMy &&, TyNodeData>::value, NodeIter
+ >::type AddNode(TyNodeDataMy &&data)
+ {
+ return EmplaceNode(std::forward<TyNodeDataMy>(data));
+ }
+ template<typename ...Tys>
+ NodeIter EmplaceNode(Tys &&...args)
+ {
+ vecNode.emplace_back(std::forward<Tys>(args)...);
+ return NodeIter(this, vecNode.size()-1);
+ }
+ //Ìí¼Ó±ß
+ template<typename TyEdgeDataMy>
+ typename std::enable_if<std::is_convertible<TyEdgeDataMy &&, TyEdgeData>::value, EdgeIter
+ >::type AddEdge(NodeIter fromNode, NodeIter toNode, TyEdgeDataMy &&data)
+ {
+ return EmplaceEdge(fromNode, toNode, std::forward<TyEdgeDataMy>(data));
+ }
+ //¹¹Ôì±ß
+ template<typename ...Tys>
+ EdgeIter EmplaceEdge(NodeIter fromNode, NodeIter toNode, Tys &&...args)
+ {
+ vecNode[fromNode.idxNode].vecEdge.emplace_back(
+ toNode.idxNode, std::forward<Tys>(args)...);
+ return EdgeIter(this, fromNode.idxNode, vecNode[fromNode.idxNode].vecEdge.size()-1);
+ }
+ //Ìí¼ÓË«Ïò±ß
+ template<typename TyEdgeDataMy>
+ typename std::enable_if<std::is_convertible<TyEdgeDataMy &&, TyEdgeData>::value,
+ std::pair<EdgeIter, EdgeIter>
+ >::type AddDoublyEdge(NodeIter fromNode, NodeIter toNode,
+ TyEdgeDataMy &&dataGo, TyEdgeDataMy &&dataRev)
+ {
+ auto it = AddAdge(fromNode, toNode, std::forward<TyEdgeDataMy>(dataGo));
+ return std::make_pair(it,
+ AddAdge(toNode, fromNode, std::forward<TyEdgeDataMy>(dataRev)));
+ }
+private:
+ //¹¹ÔìË«Ïò±ß¸¨Öúº¯Êý
+ template<typename TyTupGo, typename TyTupRev, size_t ...c_idxGo_s, size_t ...c_idxRev_s>
+ std::pair<EdgeIter, EdgeIter> EmplaceDoublyEdgeAssist(NodeIter fromNode,
+ NodeIter toNode, TyTupGo &&tupGo, TyTupRev &&tupRev,
+ IndexSequence<c_idxGo_s...>, IndexSequence<c_idxRev_s...>)
+ {
+ static auto funcGo = std::mem_fn(&AddonlyGraph::EmplaceEdge<
+ typename TypeAttachAttribute<TyTupGo &&, typename std::tuple_element<
+ c_idxGo_s, typename RemoveCVRef<TyTupGo>::type>::type>::type...>);
+ static auto funcRev = std::mem_fn(&AddonlyGraph::EmplaceEdge<
+ typename TypeAttachAttribute<TyTupRev &&, typename std::tuple_element<
+ c_idxRev_s, typename RemoveCVRef<TyTupRev>::type>::type>::type...>);
+ auto itGo = TupleInvoke(funcGo,
+ std::tuple_cat(std::forward_as_tuple(this, fromNode, toNode), std::forward<TyTupGo>(tupGo)));
+ auto itRev = TupleInvoke(funcRev,
+ std::tuple_cat(std::forward_as_tuple(this, toNode, fromNode), std::forward<TyTupRev>(tupRev)));
+ return std::make_pair(itGo, itRev);
+ }
+public:
+ //¹¹ÔìË«Ïò±ß£¬ÔÚtupleÀïÃæ·Å¹¹Ôì²ÎÊý
+ template<typename TyTupGo, typename TyTupRev>
+ std::pair<EdgeIter, EdgeIter> EmplaceDoublyEdge(NodeIter fromNode,
+ NodeIter toNode, TyTupGo &&tupGo, TyTupRev &&tupRev)
+ {
+ return EmplaceDoublyEdgeAssist(fromNode, toNode,
+ std::forward<TyTupGo>(tupGo), std::forward<TyTupRev>(tupRev),
+ MakeIndexSequence<std::tuple_size<
+ typename std::remove_reference<TyTupGo>::type>::value>(),
+ MakeIndexSequence<std::tuple_size<
+ typename std::remove_reference<TyTupRev>::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<typename TyNodeData, typename TyEdgeData>
+template<typename GraphTypeMy, typename TyNodeDataMy, typename TyNodeDataPure>
+class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateNodeIterAssist:
+ public std::iterator<std::bidirectional_iterator_tag, TyNodeDataMy,
+ ptrdiff_t, TyNodeDataMy *, TyNodeDataMy &>
+{
+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<typename TyNodeData, typename TyEdgeData>
+template<typename GraphTypeMy, typename TyNodeDataMy>
+class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateNodeIterAssist<
+ GraphTypeMy, TyNodeDataMy, void
+>: public std::iterator<std::bidirectional_iterator_tag, TyNodeDataMy,
+ ptrdiff_t, void, void>
+{
+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<typename TyNodeData, typename TyEdgeData>
+template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy>
+class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateNodeIter:
+ public TemplateNodeIterAssist<GraphTypeMy, TyNodeDataMy, TyNodeData>
+{
+public://ÓÑÔª
+ friend AddonlyGraph<TyNodeData, TyEdgeData>;
+ friend NodeIter;
+ friend NodeConstIter;
+ friend EdgeIter;
+ friend EdgeConstIter;
+private://¸¨ÖúÀàÐÍ
+ //¶ÔÓ¦µÄ±ßµü´úÆ÷
+ using EdgeIterMy = TemplateEdgeIter<GraphTypeMy, TyNodeDataMy, TyEdgeDataMy>;
+
+public://»ù±¾º¯Êý
+ //ĬÈϹ¹Ôì
+ TemplateNodeIter()
+ = default;
+ //¼Ì³Ð¸¨ÖúÀàµÄ¹¹Ô캯Êý
+ using TemplateNodeIterAssist<GraphTypeMy, TyNodeDataMy, TyNodeData>::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<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther>
+ bool operator ==(const TemplateNodeIter<
+ GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const
+ {
+ return this->idxNode==other.idxNode;
+ }
+ template<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther>
+ 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<typename TyNodeData, typename TyEdgeData>
+template<typename GraphTypeMy, typename TyEdgeDataMy, typename TyEdgeDataPure>
+class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateEdgeIterAssist:
+ public std::iterator<std::bidirectional_iterator_tag, TyEdgeDataMy,
+ ptrdiff_t, TyEdgeDataMy *, TyEdgeDataMy &>
+{
+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<typename TyNodeData, typename TyEdgeData>
+template<typename GraphTypeMy, typename TyEdgeDataMy>
+class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateEdgeIterAssist<
+ GraphTypeMy, TyEdgeDataMy, void
+>: public std::iterator<std::bidirectional_iterator_tag, TyEdgeDataMy,
+ ptrdiff_t, void, void>
+{
+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<typename TyNodeData, typename TyEdgeData>
+template<typename GraphTypeMy, typename TyNodeDataMy, typename TyEdgeDataMy>
+class AddonlyGraph<TyNodeData, TyEdgeData>::TemplateEdgeIter:
+ public TemplateEdgeIterAssist<GraphTypeMy, TyEdgeDataMy, TyEdgeData>
+{
+public://ÓÑÔª
+ friend AddonlyGraph<TyNodeData, TyEdgeData>;
+ friend NodeIter;
+ friend NodeConstIter;
+ friend EdgeIter;
+ friend EdgeConstIter;
+private://¸¨ÖúÀàÐÍ
+ //¶ÔÓ¦µÄ½Úµãµü´úÆ÷
+ using NodeIterMy = TemplateNodeIter<GraphTypeMy, TyNodeDataMy, TyEdgeDataMy>;
+
+public://»ù±¾º¯Êý
+ //¼Ì³Ð¸¨ÖúÀàµÄ¹¹Ô캯Êý
+ using TemplateEdgeIterAssist<GraphTypeMy, TyEdgeDataMy, TyEdgeData>::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<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther>
+ bool operator ==(const TemplateEdgeIter<
+ GraphTypeOther, TyNodeDataOther, TyEdgeDataOther> &other) const
+ {
+ return this->idxNode==other.idxNode && this->idxEdge==other.idxEdge;
+ }
+ template<typename GraphTypeOther, typename TyNodeDataOther, typename TyEdgeDataOther>
+ 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<typename Ty>
+inline void _SimplexAssistPivot(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector,
+ std::vector<Ty> &cVector, Ty &vValue, std::vector<int> &bSet, std::vector<int> &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<nNum; ++j) {
+ if(j==eIndex)
+ continue;
+ aMatrix[lIndex][j] *= aMatrix[lIndex][eIndex];
+ }
+ //ת»»¾ØÕóÆäËûÐÐ
+ for(int i=0; i<mNum; ++i) {
+ if(i==lIndex)
+ continue;
+ bVector[i] -= aMatrix[i][eIndex]*bVector[lIndex];
+ for(int j=0; j<nNum; ++j) {
+ if(j==eIndex)
+ continue;
+ aMatrix[i][j] -= aMatrix[i][eIndex]*aMatrix[lIndex][j];
+ }
+ aMatrix[i][eIndex] *= -aMatrix[lIndex][eIndex];
+ }
+ //ת»»Ä¿±êº¯Êý
+ vValue += cVector[eIndex]*bVector[lIndex];
+ for(int j=0; j<nNum; ++j) {
+ if(j==eIndex)
+ continue;
+ cVector[j] -= cVector[eIndex]*aMatrix[lIndex][j];
+ }
+ cVector[eIndex] *= -aMatrix[lIndex][eIndex];
+ //ת»»Ë÷Òý
+ std::swap(bSet[lIndex], nSet[eIndex]);
+}
+
+//µ¥´¿Ðθ¨ÖúË㷨ѭ»·Ö÷Ìå
+template<typename Ty>
+inline SimplexStatus _SimplexAssistLoop(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector,
+ std::vector<Ty> &cVector, Ty &vValue, std::vector<int> &bSet, std::vector<int> &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<Ty>::infinity();
+ for(int j=0; j<nNum; ++j) {
+ if(bFirst) {
+ if(cVector[j]>maxC) {
+ eIndex = j;
+ maxC = cVector[j];
+ }
+ }
+ else {
+ //ÍË»¯Ê±Ñ¡±êºÅ×îС
+ if(FloatGT(cVector[j], 0.0, true, ulp) && (eIndex==-1 || nSet[j]<nSet[eIndex])) {
+ eIndex = j;
+ maxC = cVector[j];
+ }
+ }
+ }
+ if(FloatLTE(maxC, 0.0, true, ulp))
+ return SimplexStatus::result;
+ //ÕÒ»»³ö±äÁ¿
+ lIndex = -1;
+ Ty minB = std::numeric_limits<Ty>::infinity();
+ for(int i=0; i<mNum; ++i) {
+ if(FloatGT(aMatrix[i][eIndex], 0.0, true, ulp)) {
+ Ty tmp = bVector[i]/aMatrix[i][eIndex];
+ if(tmp<minB) {
+ minB = tmp;
+ lIndex = i;
+ }
+ }
+ }
+ //ÅжÏÎÞ½ç
+ if(lIndex==-1) {
+ vValue = std::numeric_limits<Ty>::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<typename Ty>
+inline SimplexStatus _SimplexAssistInit(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector,
+ std::vector<Ty> &cVector, Ty &vValue, std::vector<int> &bSet, std::vector<int> &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<nNum; ++j)
+ nSet.push_back(j);
+ Ty minB = std::numeric_limits<Ty>::infinity();
+ int lIndex = -1;
+ for(int i=0; i<mNum; ++i) {
+ bSet.push_back(nNum+i);
+ if(bVector[i]<minB) {
+ minB = bVector[i];
+ lIndex = i;
+ }
+ }
+ if(FloatGTE(minB, 0.0, true, ulp))
+ return SimplexStatus::result;
+ //¹¹Ô츨Öú¹æ»®
+ Ty vValue2 = 0;
+ std::vector<Ty> cVector2(nNum+1, 0);
+ cVector2[nNum] = -1;
+ for(int i=0; i<mNum; ++i)
+ aMatrix[i].push_back(-1);
+ nSet.push_back(-1);
+ //³õʼÐýת²¢Çó½â
+ _SimplexAssistPivot(aMatrix, bVector, cVector2, vValue2, bSet, nSet, lIndex, nNum);
+ SimplexStatus status = _SimplexAssistLoop(aMatrix, bVector, cVector2, vValue2, bSet, nSet, ulp);
+ assert(status==SimplexStatus::result);
+ //ÅжϿÉÐÐÐÔ
+ status = FloatEQ(vValue2, 0.0, true, ulp) ?
+ SimplexStatus::result : SimplexStatus::infeasible;
+ //·´Ðýת¸¨Öú±äÁ¿
+ lIndex = (int)(std::find(bSet.begin(), bSet.end(), -1)-bSet.begin());
+ int eIndex;
+ if(lIndex!=mNum) {
+ eIndex = -1;
+ for(int j=0; j<nNum+1; ++j) {
+ if(FloatNEQ(aMatrix[lIndex][j], 0.0, true, ulp)) {
+ eIndex = j;
+ break;
+ }
+ }
+ assert(eIndex!=-1);
+ _SimplexAssistPivot(aMatrix, bVector, cVector2, vValue2, bSet, nSet, lIndex, eIndex);
+ }
+ else {
+ eIndex = (int)(std::find(nSet.begin(), nSet.end(), -1)-nSet.begin());
+ assert(eIndex!=nNum+1);
+ }
+ //½»»»¸¨Öú±äÁ¿
+ if(eIndex!=nNum) {
+ for(int i=0; i<mNum; ++i)
+ std::swap(aMatrix[i][eIndex], aMatrix[i][nNum]);
+ std::swap(nSet[eIndex], nSet[nNum]);
+ }
+ //È¥³ý¸¨Öú±äÁ¿
+ for(int i=0; i<mNum; ++i)
+ aMatrix[i].pop_back();
+ nSet.pop_back();
+ cVector2.assign(nNum, 0);
+ for(int j=0; j<nNum; ++j) {
+ if(nSet[j]<nNum)
+ cVector2[j] = cVector[nSet[j]];
+ }
+ for(int i=0; i<mNum; ++i) {
+ if(bSet[i]<nNum) {
+ vValue += cVector[bSet[i]]*bVector[i];
+ for(int j=0; j<nNum; ++j) {
+ cVector2[j] -= cVector[bSet[i]]*aMatrix[i][j];
+ }
+ }
+ }
+ std::swap(cVector, cVector2);
+ return status;
+}
+
+//µ¥´¿Ð稣¬Ä£°åΪ¸¡µãÊý
+//²ÎÊýΪ±ê×¼Ðͼ´£ºÏµÊý¾ØÕó¡¢³£ÊýÏòÁ¿¡¢Ä¿±êϵÊýÏòÁ¿¡¢Ä¿±ê³£ÊýÖµ£¬¸¡µã¾ø¶ÔÎó²î½ç±¶ÂÊ
+//·µ»ØÖµÎª×´Ì¬¡¢½âÏòÁ¿¡¢»ù±¾±äÁ¿ÐòºÅ¡¢·Ç»ù±¾±äÁ¿ÐòºÅ
+//aMatrix¡¢bVector¡¢cVectorÖоùΪΪ×îÖÕËɳÚÐ͵Ľṹ£¬vValueÊÇÄ¿±êÖµ
+//±ê×¼Ð͵ÄÑùÀý£º
+//MAX: cVector^T * x + vValue
+//s.t.£ºaMatrix * x <= bVector
+template<typename Ty>
+inline typename std::enable_if<std::is_floating_point<Ty>::value,
+ std::tuple<SimplexStatus, std::vector<Ty>, std::vector<int>, std::vector<int>>
+>::type SimplexAlgo(std::vector<std::vector<Ty>> &aMatrix, std::vector<Ty> &bVector,
+ std::vector<Ty> &cVector, Ty &vValue, int ulp= 2000)
+{
+ int mNum= (int)bVector.size(), nNum= (int)cVector.size();//Ô¼ÊøÊý£¬±äÁ¿Êý
+ std::vector<int> bSet, nSet;//»ù±¾¡¢·Ç»ù±¾±äÁ¿Ë÷Òýϱê
+ std::vector<Ty> 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<mNum; ++i) {
+ if(bSet[i]<nNum)
+ resVector[bSet[i]] = bVector[i];
+ }
+ return make_tuple(status, std::move(resVector), std::move(bSet), std::move(nSet));
+}
+
diff --git a/TypeExtend.h b/TypeExtend.h
new file mode 100644
index 0000000..4a6444e
--- /dev/null
+++ b/TypeExtend.h
@@ -0,0 +1,1280 @@
+#pragma once
+
+//±ê×¼¿âÀàÐÍÀ©Õ¹²Ù×÷
+//20191212-1029
+
+#include <cassert>
+#include <cmath>
+#include <cstdint>
+
+#include <type_traits>
+#include <limits>
+#include <algorithm>
+#include <utility>
+#include <tuple>
+#include <functional>
+#include <iterator>
+
+#include <string>
+
+#include <exception>
+#include <stdexcept>
+#include <random>
+#include <ratio>
+
+#include <chrono>
+
+
+
+
+//************
+//ÀàÐͱðÃûÀ©Õ¹
+//************
+
+
+//durationÀ©Õ¹
+namespace std
+{
+namespace chrono
+{
+typedef duration<long, ratio<3600*24>> days;
+typedef duration<long, ratio<3600*24*7>> weeks;
+}
+}
+
+
+
+//************
+//»ù´¡ÀàÐÍÀ©Õ¹
+//************
+
+//ÎÞÓÃռλÀàÐÍ
+template<int N>
+class BlankType
+{
+};
+
+
+
+//²âÊÔ²ÎÊýÊÇ·ñºÏ·¨Àà
+template<typename ...>
+struct ParamValidTester
+{
+ typedef void type;
+};
+
+
+//ÏÈÈ¥³ýÒýÓÃÔÙÈ¥³ý³£ÊýÒ×±äÊôÐÔ
+template<typename Ty>
+struct RemoveCVRef
+{
+ using type = typename std::remove_cv<typename std::remove_reference<Ty>::type>::type;
+};
+
+//ºóÕßÈ¥³ýÒýÓó£ÊýÒ×±äºóÊÇ·ñΪǰÕß
+template<typename TyDst, typename TySrc>
+struct IsRemoveCVRefSame:
+ std::is_same<TyDst, typename RemoveCVRef<TySrc>::type>
+{
+};
+
+
+//ºóÕß²ÎÊý°üÊÇ·ñÒª²»Ã»ÓвÎÊý£¬Òª²»Ö»ÓÐÒ»¸ö²¢ÇÒΪǰÕß
+template<typename TyDst, typename ...TySrc_S>
+struct IsNoneOrSame:
+ std::integral_constant<bool, sizeof...(TySrc_S)==0>
+{
+};
+template<typename TyDst, typename TySrc>
+struct IsNoneOrSame<TyDst, TySrc>:
+ std::is_same<TyDst, TySrc>
+{
+};
+
+//ºóÕß²ÎÊý°üÊÇ·ñÒª²»Ã»ÓвÎÊý£¬Òª²»Ö»ÓÐÒ»¸ö²¢ÇÒÈ¥³ýÒýÓó£ÊýÒ×±äºóΪǰÕß
+template<typename TyDst, typename ...TySrc_S>
+struct IsNoneOrRemoveCVRefSame:
+ std::integral_constant<bool, sizeof...(TySrc_S)==0>
+{
+};
+template<typename TyDst, typename TySrc>
+struct IsNoneOrRemoveCVRefSame<TyDst, TySrc>:
+ IsRemoveCVRefSame<TyDst, TySrc>
+{
+};
+
+
+//²âÊÔÊÇ·ñΪµü´úÆ÷
+template<class Ty, class= void>
+struct IsIteratorType:
+ std::false_type
+{
+};
+template<class Ty>
+struct IsIteratorType<Ty, typename ParamValidTester<
+ typename std::iterator_traits<Ty>::iterator_category>::type
+>: std::true_type
+{
+};
+
+
+//²âÊÔÈ¥³ý³£Ò×±äÒ×ÓÃÊôÐÔºó£¬ÊÇ·ñΪ×Ö·ûÖ¸Õ룬×Ö·ûÊý×é»òstringÀàÐÍ
+template<class Ty>
+struct IsRemoveCVRefSameSzOrString:
+ std::integral_constant<bool, IsRemoveCVRefSame<char *, Ty>::value
+ || IsRemoveCVRefSame<const char *, Ty>::value
+ || (std::is_array<typename RemoveCVRef<Ty>::type>::value
+ && IsRemoveCVRefSame<char, typename std::remove_extent<
+ typename RemoveCVRef<Ty>::type>::type>::value)
+ || IsRemoveCVRefSame<std::string, Ty>::value>
+{
+};
+
+
+
+//Éú³Éµü´úÆ÷½âÒýÓõÄÀàÐÍ£¬±£Áô³£Ò×±äÒýÓÃÊôÐÔ
+template<typename TyIt>
+struct IteratorDerefType
+{
+ using type = decltype(*std::declval<TyIt>());
+};
+
+//Éú³Éµü´úÆ÷½âÒýÓõÄÀàÐÍÔÙÈ¥³ý³£Ò×±äÒýÓÃÊôÐÔ
+template<typename TyIt>
+struct IteratorRemoveCVRefDerefType
+{
+ using type = typename RemoveCVRef<typename IteratorDerefType<TyIt>::type>::type;
+};
+
+
+
+//¸ù¾ÝÌṩÀ´Ô´ÀàÐ͵ÄÒýÓᢳ£Êý¡¢Ò×±äÊôÐÔ£¬¶ÔÄ¿µÄÀàÐ͸½¼ÓͬÑùµÄÊôÐÔ
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute
+{
+ using type = TyDst;
+};
+//³£ÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<const TySrc, TyDst>
+{
+ using type = typename std::add_const<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+//Ò×±äÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<volatile TySrc, TyDst>
+{
+ using type = typename std::add_volatile<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+//×óÖµÒýÓÃÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<TySrc &, TyDst>
+{
+ using type = typename std::add_lvalue_reference<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+//ÓÒÖµÒýÓÃÊôÐÔÌØ»¯
+template<typename TySrc, typename TyDst>
+struct TypeAttachAttribute<TySrc &&, TyDst>
+{
+ using type = typename std::add_rvalue_reference<
+ typename TypeAttachAttribute<TySrc, TyDst>::type>::type;
+};
+
+
+
+//Çóµ÷Ó÷µ»ØÖµÀàÐÍ
+template<typename TyFunc, typename ...Ty_S>
+struct InvokeReturnType
+{
+ using type = decltype(std::declval<TyFunc>()(std::declval<Ty_S>()...));
+};
+
+
+
+//ÕûÊýÐòÁÐÄ£°å
+template<size_t ...c_idx_s>
+struct IndexSequence
+{
+};
+template<>
+struct IndexSequence<>
+{
+ using value_type = size_t;
+ static constexpr size_t size()
+ {
+ return 0;
+ }
+};
+template<int c_idx, int ...c_rest_s>
+struct IndexSequence<c_idx, c_rest_s...>
+{
+ using value_type = size_t;
+ static constexpr size_t size()
+ {
+ return IndexSequence<c_rest_s...>::size()+1;
+ }
+};
+
+//ÕûÊýÄ£°åÌí¼ÓÔªËØº¯Êý
+template<size_t c_new, size_t ...c_idx_s>
+inline IndexSequence<c_idx_s..., c_new> AddIndexSequence(IndexSequence<c_idx_s...>)
+{
+ return IndexSequence<c_idx_s..., c_new>();
+}
+
+//Éú³É˳ÐòµÝÔöÕûÊýÄ£°å¸¨ÖúÀà
+template<size_t c_size>
+struct _MakeIndexSequenceAssist
+{
+ using type = decltype(AddIndexSequence<c_size-1>(
+ typename _MakeIndexSequenceAssist<c_size-1>::type()));
+};
+template<>
+struct _MakeIndexSequenceAssist<0>
+{
+ using type = IndexSequence<>;
+};
+//Éú³É˳ÐòµÝÔöÕûÊýÄ£°åÀà
+template<size_t c_size>
+using MakeIndexSequence = typename _MakeIndexSequenceAssist<c_size>::type;
+
+
+
+//Ä£°å¶¨³¤ÕûÐÎ
+template<bool c_bSigned, int c_size>
+struct TemplateInt
+{
+};
+template<>
+struct TemplateInt<true, 1>
+{
+ using type = int8_t;
+};
+template<>
+struct TemplateInt<false, 1>
+{
+ using type = uint8_t;
+};
+template<>
+struct TemplateInt<true, 2>
+{
+ using type = int16_t;
+};
+template<>
+struct TemplateInt<false, 2>
+{
+ using type = uint16_t;
+};
+template<>
+struct TemplateInt<true, 4>
+{
+ using type = int32_t;
+};
+template<>
+struct TemplateInt<false, 4>
+{
+ using type = uint32_t;
+};
+template<>
+struct TemplateInt<true, 8>
+{
+ using type = int64_t;
+};
+template<>
+struct TemplateInt<false, 8>
+{
+ using type = uint64_t;
+};
+
+
+
+//¹ãÒåµÄ±È½Ïº¯ÊýÀà
+template<typename Ty1, typename Ty2= Ty1>
+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<arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+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<typename Ty1, typename Ty2= Ty1>
+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<typename Ty1, typename Ty2= Ty1>
+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<typename Ty1, typename Ty2= Ty1>
+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<typename Ty1, typename Ty2= Ty1>
+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<typename Ty1, typename Ty2= Ty1>
+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<arg2 || arg1==arg2;
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+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<arg2 || arg1==arg2);
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+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<arg2);
+ }
+};
+template<typename Ty1, typename Ty2= Ty1>
+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<typename Ty1, typename Ty2= Ty1>
+using CompareType = std::function<bool(const Ty1 &, const Ty2 &)>;
+
+
+//±È½ÏÀຯÊýÀ©Õ¹£¬Ê¹ÓÃСÓں͵ÈÓÚº¯Êý
+template<typename Ty1, typename Ty2= Ty1>
+struct ExtendLessEqualWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendLessEqualWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &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<typename Ty1, typename Ty2= Ty1>
+struct ExtendGreaterWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendGreaterWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &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<typename Ty1, typename Ty2= Ty1>
+struct ExtendGreaterEqualWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendGreaterEqualWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &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<typename Ty1, typename Ty2= Ty1>
+struct ExtendNotEqualToWrap
+{
+ typedef bool result_type;
+ typedef Ty1 first_argument_type;
+ typedef Ty2 second_argument_type;
+public:
+ CompareType<Ty1, Ty2> funcLT;
+ CompareType<Ty1, Ty2> funcEQ;
+public:
+ explicit ExtendNotEqualToWrap(const CompareType<Ty1, Ty2> &o_funcLT,
+ const CompareType<Ty1, Ty2> &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<typename Ty>
+struct TypeHolder
+{
+ Ty hold;
+public:
+ //¹¹Ôì
+ TypeHolder(const Ty &o_hold):
+ hold(o_hold)
+ {
+ }
+ TypeHolder(Ty &&o_hold):
+ hold(std::move(o_hold))
+ {
+ }
+};
+//×óÖµÒýÓÃÌØ»¯
+template<typename Ty>
+struct TypeHolder<Ty &>
+{
+ Ty &hold;
+public:
+ //¹¹Ôì
+ TypeHolder(Ty &o_hold):
+ hold(o_hold)
+ {
+ }
+};
+//ÓÒÖµÒýÓÃÌØ»¯
+template<typename Ty>
+struct TypeHolder<Ty &&>
+{
+ Ty &&hold;
+public:
+ //¹¹Ôì
+ TypeHolder(Ty &&o_hold):
+ hold(std::move(o_hold))
+ {
+ }
+};
+
+
+
+//´æ´¢Ä³ÖµÀàÐÍ£¬²»ÄÜΪÒýÓã¬ÀàÐÍÖ§³Övoid
+template<typename Ty>
+struct ValueHolder
+{
+public:
+ using RefType = Ty &;
+ using ConstRefType = const Ty &;
+ using PtrType = Ty *;
+ using ConstPtrType = const Ty *;
+public:
+ Ty hold;
+public:
+ //Ä£°å¹¹Ôì
+ template<typename ...Ty_S>
+ explicit ValueHolder(Ty_S &&...args):
+ hold(std::forward<Ty_S>(args)...)
+ {
+ }
+};
+//voidÌØ»¯
+template<>
+struct ValueHolder<void>
+{
+ using RefType = void;
+ using ConstRefType = void;
+ using PtrType = void;
+ using ConstPtrType = void;
+};
+
+
+
+//**********************
+//ÀàÐͳÉÔ±»ò¸¨Öúº¯ÊýÀ©Õ¹
+//**********************
+
+//µ÷ÓñäÁ¿µÄÎö¹¹º¯Êý
+template<typename Ty>
+inline void CallDestruct(Ty &value)
+{
+ value.~Ty();
+}
+
+//µ÷ÓñäÁ¿µÄ¹¹Ô캯Êý£¬ÒªÇó±äÁ¿ÒѾ­Îö¹¹
+template<typename Ty, typename ...Ty_S>
+inline void CallConstruct(Ty &value, Ty_S &&...arg_s)
+{
+ new(&value) Ty(std::forward<Ty_S>(arg_s)...);
+}
+
+//µ÷ÓñäÁ¿µÄÎö¹¹º¯ÊýºÍ¹¹Ô캯Êý
+template<typename Ty, typename ...Ty_S>
+inline void CallRestruct(Ty &value, Ty_S &&...arg_s)
+{
+ CallDestruct(value);
+ CallConstruct(value, std::forward<Ty_S>(arg_s)...);
+}
+
+
+
+//ÌáÈ¡±äÁ¿µÄ×óÖµÒýÓÃ
+template<typename Ty>
+inline Ty &GetLref(Ty &&value)
+{
+ return value;
+}
+//ÌáÈ¡±äÁ¿µÄ³£×óÖµÒýÓÃ
+template<typename Ty>
+inline const Ty &GetConstLref(Ty &&value)
+{
+ return value;
+}
+
+
+//¶Ô±äÁ¿½øÐÐÖµ¿½±´
+template<typename Ty>
+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<typename Ty>
+inline typename std::enable_if<std::is_array<typename RemoveCVRef<Ty>::type>::value
+ && IsRemoveCVRefSame<char, typename std::remove_extent<
+ typename RemoveCVRef<Ty>::type>::type>::value, std::string
+>::type OverrideSzToStr(Ty &&sz)
+{
+ return std::string(std::forward<Ty>(sz));
+}
+//c·ç¸ñ×Ö·û´®×ª»¯×Ö·û´®£¬ÆäÓàÇé¿öÖØÔØ
+template<typename Ty>
+inline Ty &&OverrideSzToStr(Ty &&arg)
+{
+ return std::forward<Ty>(arg);
+}
+
+
+
+//ÕûÐαȽϸ¨Öúºê
+#define _IS_INT_TYPE(Ty1, Ty2) \
+ (std::is_integral<Ty1>::value && std::is_integral<Ty2>::value)
+#define _INT_SIGN_UNSIGN(Ty1, Ty2) \
+ ((std::is_integral<Ty1>::value && std::is_signed<Ty1>::value)\
+ && std::is_unsigned<Ty2>::value)
+
+//ÕûÐÎÀàÐͰ²È«ÅжÏСÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty1, Ty2), bool
+>::type IntLT(Ty1 num1, Ty2 num2)
+{
+ return (num1<0) ? (true)
+ : (static_cast<typename std::make_unsigned<Ty1>::type>(num1)<num2);
+}
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty2, Ty1), bool
+>::type IntLT(Ty1 num1, Ty2 num2)
+{
+ return (num2<0) ? (false)
+ : (num1<static_cast<typename std::make_unsigned<Ty2>::type>(num2));
+}
+template<typename Ty1, typename Ty2>
+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<num2;
+}
+
+//ÕûÐÎÀàÐͰ²È«ÅжϵÈÓÚ
+template<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_INT_SIGN_UNSIGN(Ty1, Ty2), bool
+>::type IntEQ(Ty1 num1, Ty2 num2)
+{
+ return (num1<0) ? (false)
+ : (static_cast<typename std::make_unsigned<Ty1>::type>(num1)==num2);
+}
+template<typename Ty1, typename Ty2>
+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<typename std::make_unsigned<Ty2>::type>(num2));
+}
+template<typename Ty1, typename Ty2>
+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<typename Ty1, typename Ty2>
+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<typename Ty1, typename Ty2>
+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<typename Ty1, typename Ty2>
+inline constexpr typename std::enable_if<_IS_INT_TYPE(Ty1, Ty2), bool
+>::type IntGTE(Ty1 num1, Ty2 num2)
+{
+ return !IntLT(num1, num2);
+}
+
+//ÕûÐÎÀàÐͰ²È«Åжϲ»µÈÓÚ
+template<typename Ty1, typename Ty2>
+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<Ty1>::value && std::is_floating_point<Ty2>::value)
+#define _FLOAT_COMMON_EPSILON(Ty1, Ty2) \
+ (std::max(std::numeric_limits<Ty1>::epsilon(), std::numeric_limits<Ty2>::epsilon()))
+#define _FLOAT_COMMON_MIN(Ty1, Ty2) \
+ (std::max(std::numeric_limits<Ty1>::min(), std::numeric_limits<Ty2>::min()))
+#define _FLOAT_ABS(num) ((num)>=0? (num):-(num))
+
+//¸¡µãÊý±È½ÏÏàµÈ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+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<typename Ty1, typename Ty2>
+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<num2 && !FloatEQ(num1, num2, bAbs, ulp);
+}
+
+//¸¡µãÊý±È½ÏСÓÚµÈÓÚ£¬±£Ö¤Âß¼­¹ØÏµ
+template<typename Ty1, typename Ty2>
+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<typename Ty1, typename Ty2>
+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<typename Ty1, typename Ty2>
+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<typename Ty1, typename Ty2>
+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<typename Ty>
+inline typename std::enable_if<std::is_floating_point<Ty>::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<typename Ty>
+inline typename std::enable_if<std::is_floating_point<Ty>::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<typename Ele, typename Ty>
+inline std::string &operator <<(std::basic_string<Ele> &str, Ty &&arg)
+{
+ return str += std::forward<Ty>(arg);
+}
+
+
+
+//·¶Î§ÄÚ×ÖµäÐò±È½Ï²Ù×÷£¬Ê¹Óõü´úÆ÷£¬Ð¡ÓÚµÈÓÚ´óÓڷֱ𷵻Ø-1,0,1
+template<typename TyIt1, typename TyIt2,
+ typename TyLess= GeneralLess<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::type>,
+ typename TyEqual= GeneralEqualTo<typename IteratorRemoveCVRefDerefType<TyIt1>::type,
+ typename IteratorRemoveCVRefDerefType<TyIt2>::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<typename Ty>
+struct IsTupleType:
+ std::false_type
+{
+};
+template<typename ...Ty_S>
+struct IsTupleType<std::tuple<Ty_S...>>:
+ std::true_type
+{
+};
+
+
+//tupleÀàÐÍת»»À©Õ¹¸¨Öúº¯Êý
+template<typename TyDst, typename TySrc, size_t ...c_idx_s>
+inline TyDst _TupleCastAssist(TySrc &&src, IndexSequence<c_idx_s...>)
+{
+ return TyDst(std::get<c_idx_s>(std::forward<TySrc>(src))...);
+}
+//tupleÀàÐÍת»»À©Õ¹£¬Ö±½ÓÍêÃÀת·¢ÒÔÖ§³ÖËùÓеÄÒýÓÃÇé¿ö£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë
+//Ô´ÀàÐÍÐèÒªÄܱ»getº¯Êý²ð½â£¬Ä¿µÄÀàÐÍÐèÒªÄܽÓÊÜÔ´ÀàÐͲð½âºóµÄ¹¹Ô캯Êý
+template<typename TyDst, typename TySrc>
+inline TyDst TupleCast(TySrc &&src)
+{
+ return _TupleCastAssist<TyDst>(std::forward<TySrc>(src), MakeIndexSequence<
+ std::tuple_size<typename std::remove_reference<TySrc>::type>::value>());
+}
+
+
+
+//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐ͸¨ÖúÀàÐÍ
+template<typename TyFunc, typename TyTup, typename TyIdx>
+struct _TupleInvokeReturnTypeAssist
+{
+};
+template<typename TyFunc, typename TyTup, size_t ...c_idx_s>
+struct _TupleInvokeReturnTypeAssist<TyFunc, TyTup, IndexSequence<c_idx_s...>>
+{
+ using type = decltype(std::declval<TyFunc>()(std::get<c_idx_s>(std::declval<TyTup>())...));
+};
+//tupleÀàÐ͵÷Óú¯Êý·µ»ØÖµÀàÐÍ£¬Ê¹ÓôøcvrefµÄÀàÐÍ´«Èë
+template<typename TyFunc, typename TyTup>
+struct TupleInvokeReturnType
+{
+ using type = typename _TupleInvokeReturnTypeAssist<TyFunc, TyTup, MakeIndexSequence<
+ std::tuple_size<typename std::remove_reference<TyTup>::type>::value>>::type;
+};
+
+//tupleÀàÐ͵÷Óú¯Êý¸¨Öúº¯Êý
+template<typename TyFunc, typename TyTup, size_t ...c_idx_s>
+inline typename TupleInvokeReturnType<TyFunc &&, TyTup &&
+>::type _TupleInvokeAssist(TyFunc &&func, TyTup &&tup, IndexSequence<c_idx_s...>)
+{
+ return std::forward<TyFunc>(func)(std::get<c_idx_s>(std::forward<TyTup>(tup))...);
+}
+//tupleÀàÐ͵÷Óú¯Êý£¬±¾ÖÊÉÏÖ»ÒªÄܱ»getº¯Êý²ð½â¼´¿É£¬ÈôÐèÓÒÖµÔò½«tupleÒÔÓÒÖµ´«Èë
+template<typename TyFunc, typename TyTup>
+inline typename TupleInvokeReturnType<TyFunc &&, TyTup &&
+>::type TupleInvoke(TyFunc &&func, TyTup &&tup)
+{
+ return _TupleInvokeAssist(std::forward<TyFunc>(func), std::forward<TyTup>(tup),
+ MakeIndexSequence<std::tuple_size<typename std::remove_reference<TyTup>::type>::value>());
+}
+
+
+
+//hashµ÷Óú¯Êý
+template<typename Ty>
+inline auto HashFunc(Ty &&arg)->
+decltype(std::hash<typename RemoveCVRef<Ty>::type>()(std::forward<Ty>(arg)))
+{
+ return std::hash<typename RemoveCVRef<Ty>::type>()(std::forward<Ty>(arg));
+}
+
+
+//hashµÄÌØÀý»¯
+namespace std
+{
+//¶ÔpairÌØÀý»¯£¬Ã»Óн»»»²»±äÐÔ£¬Óëtuple¼æÈÝ
+template<typename Ty1, typename Ty2>
+struct hash<std::pair<Ty1, Ty2>>
+{
+ typedef size_t result_type;
+ typedef std::pair<Ty1, Ty2> argument_type;
+ result_type operator()(const argument_type &pr) const
+ {
+ return HashFunc(HashFunc(pr.first))
+ ^ HashFunc(pr.second);
+ }
+};
+
+//¶ÔtupleÌØÀý»¯£¬Ã»Óн»»»²»±äÐÔ
+template<typename ...Tys>
+struct hash<std::tuple<Tys...>>
+{
+ typedef size_t result_type;
+ typedef std::tuple<Tys...> argument_type;
+ result_type operator()(const argument_type &tup) const
+ {
+ return Assist<sizeof...(Tys)>(tup);
+ }
+private:
+ template<size_t c_index>
+ static typename std::enable_if<c_index>=2, result_type
+ >::type Assist(const std::tuple<Tys...> &tup)
+ {
+ return HashFunc(Assist<c_index-1>(tup))
+ ^ HashFunc(std::get<c_index-1>(tup));
+ }
+ template<size_t c_index>
+ static typename std::enable_if<c_index==1, result_type
+ >::type Assist(const std::tuple<Tys...> &tup)
+ {
+ return HashFunc(std::get<0>(tup));
+ }
+ template<size_t c_index>
+ static typename std::enable_if<c_index==0, result_type
+ >::type Assist(const std::tuple<Tys...> &tup)
+ {
+ return 0;
+ }
+};
+}
+
+
+//¸÷Ààµü´úÆ÷hashÀ࣬βºóµü´úÆ÷½âÒýÓò»°²È«
+template<typename Ty>
+struct IteratorHash
+{
+ typedef size_t result_type;
+ typedef Ty argument_type;
+ result_type operator()(argument_type it) const
+ {
+ return std::hash<decltype(&*it)>()(&*it);
+ }
+};
+
+
+
+//¸÷Ààµü´úÆ÷±È½ÏÀ࣬βºóµü´úÆ÷½âÒýÓò»°²È«
+template<typename Ty>
+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<typename Ty>
+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<typename Ty>
+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<typename Ty>
+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 <cstdio>
+#include <cassert>
+
+#include <iostream>
+
+#include <type_traits>
+#include <utility>
+
+#include <string>
+
+#include <exception>
+#include <stdexcept>
+
+
+//**********
+//±êʶ·û²Ù×÷
+//**********
+
+#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<decltype(arr)>::type))//ÇóÊý×é´óС
+
+#define ARR_SIZE_ALL(arr) (sizeof(decltype(arr))\
+ /sizeof(typename std::remove_all_extents<decltype(arr)>::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<Ty>(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<Ty>(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<Ty>(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<Ty>(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<Typename>(arg));\
+ }//Ä£°å¸³Öµ£¬×Ô¸³Öµ²»°²È«£¬×¢Òâ»á¸²¸ÇÐé±í£¬²»½¨ÒéʹÓÃ
+
+#define TEMPLATE_PACKET_ASSIGN(Type, Typenames, args) {\
+ this->~Type();\
+ new(this) Type(std::forward<Typenames>(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
+