SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
|
00001 /* sdsl - succinct data structures library 00002 Copyright (C) 2009 Simon Gog 00003 00004 This program is free software: you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation, either version 3 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program. If not, see http://www.gnu.org/licenses/ . 00016 */ 00021 #ifndef INCLUDED_SDSL_RMQ_SUPPORT_SPARSE_TABLE 00022 #define INCLUDED_SDSL_RMQ_SUPPORT_SPARSE_TABLE 00023 00024 #include "rmq_support.hpp" 00025 #include "int_vector.hpp" 00026 #include "bitmagic.hpp" 00027 #include <ostream> 00028 00030 namespace sdsl 00031 { 00032 00033 00034 template<class RandomAccessContainer = int_vector<>, bool Minimum=true> 00035 class rmq_support_sparse_table; 00036 00037 00038 // see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1406.pdf for a proposal for a better solution 00039 template<class RandomAccessContainer = int_vector<> > 00040 struct range_maximum_support_sparse_table { 00041 typedef rmq_support_sparse_table<RandomAccessContainer, false> type; 00042 }; 00043 00045 00055 template<class RandomAccessContainer, bool Minimum> 00056 class rmq_support_sparse_table 00057 { 00058 const RandomAccessContainer* m_v; // pointer to the supported random access container 00059 bit_vector::size_type m_k; // size of m_table 00060 int_vector<>* m_table; 00061 typedef min_max_trait<RandomAccessContainer, Minimum> mm_trait; 00062 00063 void construct() { 00064 if (m_v == NULL) 00065 return; 00066 const size_type n = m_v->size(); 00067 if (n < 2) // for n<2 the queries could be answerd without any table 00068 return; 00069 size_type k=0; 00070 while (2*(1ULL<<k) < n) ++k; // calculate maximal 00071 if (!(m_table == NULL)) 00072 delete [] m_table; 00073 m_table = new int_vector<>[k]; 00074 m_k = k; 00075 for (size_type i=0; i<k; ++i) { 00076 m_table[i] = int_vector<>(n-(1<<(i+1))+1, 0, i+1); 00077 } 00078 for (size_type i=0; i<n-1; ++i) { 00079 if (!mm_trait::compare((*m_v)[i], (*m_v)[i+1])) 00080 m_table[0][i] = 1; 00081 // std::cerr<<i+m_table[0][i]<<" "; 00082 } 00083 // std::cerr<<std::endl; 00084 for (size_type i=1; i<k; ++i) { 00085 for (size_type j=0; j<m_table[i].size(); ++j) { 00086 m_table[i][j] = mm_trait::compare((*m_v)[j+m_table[i-1][j]], (*m_v)[j+(1<<i)+m_table[i-1][j+(1<<i)]]) ? m_table[i-1][j] : (1<<i)+m_table[i-1][j+(1<<i)]; 00087 // std::cerr<<j+m_table[i][j]<<" "; 00088 } 00089 // std::cerr<<std::endl; 00090 } 00091 } 00092 00093 void copy(const rmq_support_sparse_table& rm) { 00094 m_v = rm.m_v; 00095 m_k = rm.m_k; 00096 if (m_table != NULL) { 00097 delete [] m_table; 00098 m_table = NULL; 00099 } 00100 if (m_k > 0) { 00101 m_table = new int_vector<>[m_k]; 00102 for (size_type i=0; i<m_k; ++i) 00103 m_table[i] = rm.m_table[i]; 00104 } 00105 } 00106 00107 public: 00108 typedef typename RandomAccessContainer::size_type size_type; 00109 typedef typename RandomAccessContainer::size_type value_type; 00110 00111 rmq_support_sparse_table(const RandomAccessContainer* v=NULL):m_v(v), m_k(0), m_table(NULL) { 00112 construct(); 00113 } 00114 00116 rmq_support_sparse_table(const rmq_support_sparse_table& rm) { 00117 if (this != &rm) { // if v is not the same object 00118 copy(rm); 00119 } 00120 } 00121 00122 00123 ~rmq_support_sparse_table() { 00124 if (m_table != NULL) 00125 delete [] m_table; 00126 } 00127 00128 rmq_support_sparse_table& operator=(const rmq_support_sparse_table& rm) { 00129 if (this != &rm) { 00130 copy(rm); 00131 } 00132 return *this; 00133 } 00134 00135 void swap(rmq_support_sparse_table& rm) { 00136 std::swap(m_k, rm.m_k); 00137 std::swap(m_table, rm.m_table); 00138 } 00139 00140 void set_vector(const RandomAccessContainer* v) { 00141 m_v = v; 00142 } 00143 00145 00155 size_type operator()(const size_type l, const size_type r)const { 00156 assert(l <= r); assert(r < size()); 00157 if (l==r) 00158 return l; 00159 if (l+1 == r) 00160 return mm_trait::compare((*m_v)[l],(*m_v)[r]) ? l : r; 00161 size_type k = bit_magic::l1BP(r-l); 00162 const size_type rr = r-(1<<k)+1; 00163 return mm_trait::compare((*m_v)[l+m_table[k-1][l]], (*m_v)[rr+m_table[k-1][rr]]) ? l+m_table[k-1][l] : rr+m_table[k-1][rr]; 00164 } 00165 00166 size_type size()const { 00167 if (m_v == NULL) 00168 return 0; 00169 else 00170 return m_v->size(); 00171 } 00172 00173 size_type serialize(std::ostream& out, structure_tree_node* v=NULL, std::string name="")const { 00174 size_type written_bytes = 0; 00175 structure_tree_node* child = structure_tree::add_child(v, name, util::class_name(*this)); 00176 written_bytes += util::write_member(m_k, out); 00177 if (m_k > 0) { 00178 assert(m_table != NULL); 00179 for (size_type i=0; i < m_k; ++i) 00180 written_bytes += m_table[i].serialize(out); 00181 } 00182 structure_tree::add_size(child, written_bytes); 00183 return written_bytes; 00184 } 00185 00186 void load(std::istream& in, const RandomAccessContainer* v) { 00187 set_vector(v); 00188 util::read_member(m_k, in); 00189 if (m_k >0) { 00190 if (m_table != NULL) 00191 delete [] m_table; 00192 m_table = new int_vector<>[m_k]; 00193 for (size_type i=0; i < m_k; ++i) 00194 m_table[i].load(in); 00195 } 00196 } 00197 }; 00198 00199 }// end namespace sds 00200 00201 #endif // end file