2563 lines
68 KiB
C
2563 lines
68 KiB
C
|
|
#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));
|
|||
|
|
}
|
|||
|
|
|