This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangshuo1-domain-classific…/StruAndAlgo.h

2563 lines
68 KiB
C
Raw Permalink Normal View History

#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));
}