SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
 All Classes Namespaces Files Functions Variables Typedefs Friends
sdsl/include/sdsl/rmq_support_sparse_table.hpp
Go to the documentation of this file.
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