STL中,list的优点是插入、删除性能极佳(时间复杂度只需O(1)即可),而且非常重要的在删除节点后,其迭代器不失效,但list查找却不擅长。map由于其实现的数据结构为rb-tree,因此,其插入、删除以及查找的性能也都是非常不错的。如:插入、删除操作在多数情况下,可能只需要几个简单的数据交换、节点旋转即可达到目的,在这样情况下,时间复杂度也只有O(1)即可(当然,在最糟糕情况下,如插入、删除的时候产生上溯时,则时间复杂度最坏情况有可能达到2logN = O(logN),但由于rb-tree的性质原因,会产生最坏情况的机会也会比较少,而且大量试验证明,rb-tree的平均性能都是非常好的)。但是map容器在删除节点时,其迭代器是失效的。

但在项目开发(尤其是在游戏项目开发)中,像设计角色管理器、技能管理器、buff管理器等等时候,经常会遇到这样一个问题(说明:此处以角色管理器为例说明)如下:

问题

游戏中(或战场中吧),每一个角色对象都有一个唯一Id,那么,这些游戏中的对象该如何维护?

解决

见过有的项目中是将这些角色对象用map来维护的。看上去好像是比较理想,因为它查找非常方便,而且在实际当中,也的的确确是需要频繁根据唯一Id查找对应的角色对象。但用map有个问题,在这些对象更新时,有可能会遇到角色死亡的情况,此时该如何处理这个对象?是立即移除?是先打标记然后再在全部更新之后,再一次性全部移除?又或者是都不移除只是不再更新它而已?事实上,这些处理方案都不理想。事实上,用这个方案的项目,最终的结果是:因为没办法在更新时移时移除掉这些“垃圾”角色对象,性能好坏且不说,整个代码最后都显得比较乱。因为用户在到处查找使用时,都是小心查看取出来的该对象是否是有效的。

另一种维护方案是使用list。该方案不必多说,数据组织与更新、移除都没啥大问题,就是查找效率不高。

鉴于前面综述情况,特地设计一个容器适配器GFStableList,其功能类似list,但却具有map的查找性能,并且支持erase时,reverse_iterator参数。编码如下:

  1 #pragma once
  2
  3 #include "src/Common/IncludeHeaders.h"
  4
  5 /******************************************************************************
  6  * create   : (jacc.kim) [3-1-2016]
  7  * summary  : class GFStableList.
  8  * !!!note  : 01.该列表中的元素的"Id"是不可以重复的.
  9  *            02.该列表稳定、支持快速查找、类似std::list删除时迭代器有效.
 10  *            03.使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
 11  *               使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
 12  *               使用时必需要设置 IdGetter 与 ValueDeleter 两个参数!!!
 13 ******************************************************************************/
 14 template<typename TValue, typename TId>
 15 class GFStableList
 16 {
 17 public:
 18     typedef typename std::list<TValue>                          value_list;
 19     typedef typename value_list::value_type                     value_type;
 20     typedef typename value_list::pointer                        pointer;
 21     typedef typename value_list::const_pointer                  const_pointer;
 22     typedef typename value_list::reference                      reference;
 23     typedef typename value_list::const_reference                const_reference;
 24     typedef typename value_list::difference_type                difference_type;
 25     typedef typename value_list::size_type                      size_type;
 26     typedef typename value_list::iterator                       iterator;
 27     typedef typename value_list::const_iterator                 const_iterator;
 28     typedef typename value_list::reverse_iterator               reverse_iterator;
 29     typedef typename value_list::const_reverse_iterator         const_reverse_iterator;
 30
 31     typedef typename TId                                        id_type;
 32     typedef typename std::function<id_type(const_reference)>    TGFvalueIdGetter;
 33     typedef typename std::function<void(const_reference)>       TGFvalueDeleter;
 34
 35 public:
 36     GFStableList();
 37     explicit GFStableList(const TGFvalueIdGetter& getter);
 38     GFStableList(const TGFvalueIdGetter& getter, const TGFvalueDeleter& deleter);
 39     ~GFStableList();
 40
 41     void                                setValueIdGetter(const TGFvalueIdGetter& getter);
 42     void                                setValueDeleter(const TGFvalueDeleter& deleter);
 43
 44     // !!!note: only no exist items & valid items will be insert or push.
 45     const bool                          push_front(const_reference value);
 46     const bool                          push_back(const_reference value);
 47     iterator                            insert(const_iterator _where, const_reference value);
 48     iterator                            insert(const_iterator _where, const_iterator _first, const_iterator _last);
 49
 50     iterator                            erase(const_reference value);
 51     iterator                            erase(const id_type& id);
 52     iterator                            erase(const_iterator _first, const_iterator _last);
 53     iterator                            erase(const_iterator _where);
 54     reverse_iterator                    erase(reverse_iterator _first, reverse_iterator _last);
 55     reverse_iterator                    erase(reverse_iterator _where);
 56     const_reverse_iterator              erase(const_reverse_iterator _first, const_reverse_iterator _last);
 57     const_reverse_iterator              erase(const_reverse_iterator _where);
 58     void                                clear();
 59     iterator                            find(const id_type& id);
 60     const_iterator                      find(const id_type& id) const;
 61
 62     iterator                            begin();
 63     const_iterator                      begin() const;
 64     iterator                            end();
 65     const_iterator                      end() const;
 66
 67     reverse_iterator                    rbegin();
 68     const_reverse_iterator              rbegin() const;
 69     reverse_iterator                    rend();
 70     const_reverse_iterator              rend() const;
 71
 72     const_iterator                      cbegin() const;
 73     const_iterator                      cend() const;
 74     const_reverse_iterator              crbegin() const;
 75     const_reverse_iterator              crend() const;
 76
 77     reference                           front();
 78     reference                           back();
 79     const_reference                     front() const;
 80     const_reference                     back() const;
 81
 82     void                                pop_front();
 83     void                                pop_back();
 84
 85     bool                                empty();
 86     size_type                           size();
 87
 88 private:
 89     GFStableList(const GFStableList<TValue, TId>& listValues) = delete;
 90
 91 private:
 92     typedef typename std::map<id_type, iterator>        id_value_map;
 93
 94     void                                _clearValueList();
 95     void                                _clearMapping();
 96     iterator                            _locate(const_reference value);
 97     const_iterator                      _locate(const_reference value) const;
 98     iterator                            _locate(const id_type& id);
 99     const_iterator                      _locate(const id_type& id) const;
100     const bool                          _isExisted(const id_type& id);
101     const bool                          _isExisted(const_reference value);
102     const id_type                       _getValueId(const_reference value);
103
104 private:
105     TGFvalueIdGetter                    m_IdGetter;
106     TGFvalueDeleter                     m_ValueDeleter;
107     value_list                          m_listValues;
108     id_value_map                        m_mapMapping;
109
110 };//template<typename TValue, typename TId> class GFStableList
111
112 #include "src/Common/GFStableList.inl"

GFStableList.h文件

  1 #include "src/Common/IncludeHeaders.h"
  2
  3 ///
  4 // template<typename TValue, typename TId> class GFStableList
  5 template<typename TValue, typename TId>
  6 GFStableList<TValue, TId>::GFStableList() : m_IdGetter    (nullptr)
  7                                           , m_ValueDeleter(nullptr)
  8                                           , m_listValues  ()
  9                                           , m_mapMapping  ()
 10 {
 11
 12 }
 13
 14 template<typename TValue, typename TId>
 15 GFStableList<TValue, TId>::GFStableList(const TGFvalueIdGetter& getter) : m_IdGetter    (getter)
 16                                                                         , m_ValueDeleter(nullptr)
 17                                                                         , m_listValues  ()
 18                                                                         , m_mapMapping  ()
 19 {
 20
 21 }
 22
 23 template<typename TValue, typename TId>
 24 GFStableList<TValue, TId>::GFStableList(const TGFvalueIdGetter& getter, const TGFvalueDeleter& deleter) : m_IdGetter    (getter)
 25                                                                                                         , m_ValueDeleter(deleter)
 26                                                                                                         , m_listValues  ()
 27                                                                                                         , m_mapMapping  ()
 28 {
 29
 30 }
 31
 32 template<typename TValue, typename TId>
 33 GFStableList<TValue, TId>::~GFStableList() {
 34     this->clear();
 35 }
 36
 37 template<typename TValue, typename TId>
 38 void GFStableList<TValue, TId>::setValueIdGetter(const TGFvalueIdGetter& getter) {
 39     m_IdGetter = getter;
 40     //GFAssert(nullptr != m_IdGetter, "the id getter is nullptr.");
 41 }
 42
 43 template<typename TValue, typename TId>
 44 void GFStableList<TValue, TId>::setValueDeleter(const TGFvalueDeleter& deleter) {
 45     m_ValueDeleter = deleter;
 46 }
 47
 48 template<typename TValue, typename TId>
 49 const bool GFStableList<TValue, TId>::push_front(const_reference value) {
 50     return insert(begin(), value) != end();
 51 }
 52
 53 template<typename TValue, typename TId>
 54 const bool GFStableList<TValue, TId>::push_back(const_reference value) {
 55     return insert(end(), value) != end();
 56 }
 57
 58 template<typename TValue, typename TId>
 59 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::insert(const_iterator _where, const_reference value) {
 60     if (nullptr == value) {
 61         return end();
 62     }
 63
 64     const auto id = _getValueId(value);
 65     if (_isExisted(id)) {
 66         return end();// 已经存在了.
 67     }
 68
 69     auto iter = m_listValues.insert(_where, value);
 70     m_mapMapping[id] = iter;
 71     return iter;
 72 }
 73
 74 template<typename TValue, typename TId>
 75 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::insert(const_iterator _where, const_iterator _first, const_iterator _last) {
 76     if (_first == end() || _first == _last) {
 77         return;
 78     }
 79     auto insert_pos = end();
 80     iterator tmpResult;
 81     id_type id;
 82     for (auto iter = _first; iter != _last; ++iter) {
 83         id = _getValueId(*iter);
 84         if (_isExisted(id)) {
 85             continue;// id is existed.
 86         }
 87         tmpResult = m_listValues.insert(_where, *iter);
 88         m_mapMapping[id] = tmpResult;
 89
 90         if (insert_pos == end()) {
 91             insert_pos = tmpResult;
 92         }
 93     }
 94     return insert_pos;
 95 }
 96
 97 template<typename TValue, typename TId>
 98 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_reference value) {
 99     auto iter = _locate(value);
100     return erase(iter);
101 }
102
103 template<typename TValue, typename TId>
104 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const id_type& id) {
105     auto iter = _locate(id);
106     return erase(iter);
107 }
108
109 template<typename TValue, typename TId>
110 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_iterator _first, const_iterator _last) {
111     if (_first == end()) {
112         return end();
113     }
114     if (_first == begin() && _last == end()) {
115         this->clear();
116         return end();
117     }
118     iterator retIter = end();
119     auto iter = _first;
120     while (iter != _last && iter != end()) {
121         retIter = this->erase(iter);
122         iter = retIter;
123     }
124     return retIter;
125 }
126
127 template<typename TValue, typename TId>
128 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::erase(const_iterator _where) {
129     if (_where == end()) {
130         return end();
131     }
132     const auto id = _getValueId(*_where);
133     m_mapMapping.erase(id);
134     return m_listValues.erase(_where);
135 }
136
137 template<typename TValue, typename TId>
138 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::erase(reverse_iterator _first, reverse_iterator _last) {
139     if (_first == rend()) {
140         return rend();
141     }
142     if (_first == rbegin() && _last == rend()) {
143         this->clear();
144         return rend();
145     }
146     reverse_iterator retIter = rend();
147     auto iter = _first;
148     while (iter != _last && iter != rend()) {
149         retIter = this->erase(iter);
150         iter = retIter;
151     }
152     return retIter;
153 }
154
155 template<typename TValue, typename TId>
156 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::erase(reverse_iterator _where) {
157     if (_where == rend()) {
158         return rend();
159     }
160
161     auto ret_iter = _where; // 返回值.
162     ++ret_iter;
163
164     const auto id = _getValueId(*_where.base());
165     this->erase(id);
166
167     return ret_iter;
168 }
169
170 template<typename TValue, typename TId>
171 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::erase(const_reverse_iterator _first, const_reverse_iterator _last) {
172     if (_first == rend()) {
173         return rend();
174     }
175     if (_first == rbegin() && _last == rend()) {
176         this->clear();
177         return rend();
178     }
179     const_reverse_iterator retIter = rend();
180     auto iter = _first;
181     while (iter != _last && iter != rend()) {
182         retIter = this->erase(iter);
183         iter = retIter;
184     }
185     return retIter;
186 }
187
188 template<typename TValue, typename TId>
189 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::erase(const_reverse_iterator _where) {
190     if (_where == rend()) {
191         return rend();
192     }
193
194     auto ret_iter = _where; // 返回值.
195     ++ret_iter;
196
197     const auto id = _getValueId(*_where.base());
198     this->erase(id);
199
200     return ret_iter;
201 }
202
203 template<typename TValue, typename TId>
204 void GFStableList<TValue, TId>::clear() {
205     _clearValueList();
206     _clearMapping();
207 }
208
209 template<typename TValue, typename TId>
210 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::find(const id_type& id) {
211     return _locate(id);
212 }
213
214 template<typename TValue, typename TId>
215 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::find(const id_type& id) const {
216     return _locate(id);
217 }
218
219 template<typename TValue, typename TId>
220 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::begin() {
221     return m_listValues.begin();
222 }
223
224 template<typename TValue, typename TId>
225 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::begin() const {
226     return m_listValues.begin();
227 }
228
229 template<typename TValue, typename TId>
230 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::end() {
231     return m_listValues.end();
232 }
233
234 template<typename TValue, typename TId>
235 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::end() const {
236     return m_listValues.end();
237 }
238
239 template<typename TValue, typename TId>
240 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::rbegin() {
241     return m_listValues.rbegin();
242 }
243
244 template<typename TValue, typename TId>
245 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::rbegin() const {
246     return m_listValues.rbegin();
247 }
248
249 template<typename TValue, typename TId>
250 typename GFStableList<TValue, TId>::reverse_iterator GFStableList<TValue, TId>::rend() {
251     return m_listValues.rend();
252 }
253
254 template<typename TValue, typename TId>
255 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::rend() const {
256     return m_listValues.rend();
257 }
258
259 template<typename TValue, typename TId>
260 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::cbegin() const {
261     return m_listValues.cbegin();
262 }
263
264 template<typename TValue, typename TId>
265 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::cend() const {
266     return m_listValues.cend();
267 }
268
269 template<typename TValue, typename TId>
270 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::crbegin() const {
271     return m_listValues.crbegin();
272 }
273
274 template<typename TValue, typename TId>
275 typename GFStableList<TValue, TId>::const_reverse_iterator GFStableList<TValue, TId>::crend() const {
276     return m_listValues.crend();
277 }
278
279 template<typename TValue, typename TId>
280 typename GFStableList<TValue, TId>::reference GFStableList<TValue, TId>::front() {
281     return m_listValues.front();
282 }
283
284 template<typename TValue, typename TId>
285 typename GFStableList<TValue, TId>::reference GFStableList<TValue, TId>::back() {
286     return m_listValues.back();
287 }
288
289 template<typename TValue, typename TId>
290 typename GFStableList<TValue, TId>::const_reference GFStableList<TValue, TId>::front() const {
291     return m_listValues.front();
292 }
293
294 template<typename TValue, typename TId>
295 typename GFStableList<TValue, TId>::const_reference GFStableList<TValue, TId>::back() const {
296     return m_listValues.end();
297 }
298
299 template<typename TValue, typename TId>
300 void GFStableList<TValue, TId>::pop_front() {
301     if (this->empty()) {
302         return;
303     }
304     auto iter = this->begin();
305     const auto id = _getValueId(*iter);
306     this->erase(id);
307 }
308
309 template<typename TValue, typename TId>
310 void GFStableList<TValue, TId>::pop_back() {
311     if (this->empty()) {
312         return;
313     }
314     auto riter = this->rbegin();
315     const auto id = _getValueId(*riter);
316     this->erase(id);
317 }
318
319 template<typename TValue, typename TId>
320 bool GFStableList<TValue, TId>::empty() {
321     return m_listValues.empty();
322 }
323
324 template<typename TValue, typename TId>
325 typename GFStableList<TValue, TId>::size_type GFStableList<TValue, TId>::size() {
326     return m_listValues.size();
327 }
328
329 template<typename TValue, typename TId>
330 void GFStableList<TValue, TId>::_clearValueList() {
331     if (nullptr != m_ValueDeleter) {
332         auto iter = m_listValues.begin();
333         auto iterend = m_listValues.end();
334         for (; iter != iterend; ++iter) {
335             m_ValueDeleter(*iter);
336         }
337     }
338     m_listValues.clear();
339 }
340
341 template<typename TValue, typename TId>
342 void GFStableList<TValue, TId>::_clearMapping() {
343     m_mapMapping.clear();
344 }
345
346 template<typename TValue, typename TId>
347 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::_locate(const_reference value) {
348     const auto id = m_IdGetter(value);
349     return _locate(id);
350 }
351
352 template<typename TValue, typename TId>
353 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::_locate(const_reference value) const {
354     const auto id = m_IdGetter(value);
355     return _locate(id);
356 }
357
358 template<typename TValue, typename TId>
359 typename GFStableList<TValue, TId>::iterator GFStableList<TValue, TId>::_locate(const id_type& id) {
360     auto iter = m_mapMapping.find(id);
361     if (iter == m_mapMapping.end()) {
362         return end();
363     }
364     return iter->second;
365 }
366
367 template<typename TValue, typename TId>
368 typename GFStableList<TValue, TId>::const_iterator GFStableList<TValue, TId>::_locate(const id_type& id) const {
369     auto iter = m_mapMapping.find(id);
370     if (iter == m_mapMapping.end()) {
371         return end();
372     }
373     return iter->second;
374 }
375
376 template<typename TValue, typename TId>
377 const bool GFStableList<TValue, TId>::_isExisted(const id_type& id) {
378     auto iter = m_mapMapping.find(id);
379     return iter != m_mapMapping.end();
380 }
381
382 template<typename TValue, typename TId>
383 const bool GFStableList<TValue, TId>::_isExisted(const_reference value) {
384     auto id = _getValueId(value);
385     return _isExisted(id);
386 }
387
388 template<typename TValue, typename TId>
389 typename const GFStableList<TValue, TId>::id_type GFStableList<TValue, TId>::_getValueId(const_reference value) {
390     return m_IdGetter(value);
391 }

GFStableList.inl文件

转载于:https://www.cnblogs.com/tongy0/p/5622329.html

GFStableList Adapter相关推荐

  1. Android ListView (多个adapter 说明)

    最近维护项目,项目里面使用的都是ListView 这里也对ListView 回顾一下 以下 demo 地址 ListView 在Android 里面用来实现列表的, 在xml 中创建ListView ...

  2. RecyclerView Adapter中notifyDataSetChanged 的作用

    一直认为notifyDataSetChanged  是 用来刷新数据的 当数据发生变化的时候调用notifyDataSetChanged 官方说:通知任何注册的观察者数据发生了改变(Notify an ...

  3. (1)Adapter适配器(ArrayAdapter、SimpleAdapter、BaseAdapter)

    ArrayAdapter(数组适配器) ArrayAdapter只能显示一行文本数据 ArrayAdapter(@NonNull Context context, @LayoutRes int res ...

  4. Adapter的getView

    http://blog.csdn.net/yelbosh/article/details/7831812 BaseAdapter就Android应用程序中经常用到的基础数据适配器,它的主要用途是将一组 ...

  5. 设计模式之适配器模式(Adapter)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  6. java getitemcount_RecyclerView.Adapter中的getItemCount() 返回数组的size是出现异常?

    1.问题描述:RecyclerView.Adapter中的getItemCount() 返回数组的size是出现异常.网络用的是okhttp,数据库框架是litepal,功能是从网络上获取JSON数据 ...

  7. Java 事件适配器 Adapter

    事件适配器Adapters 在上一篇文章中: http://www.cnblogs.com/mengdd/archive/2013/02/06/2908241.html 第二个例子中,可以看到要实现相 ...

  8. 设计模式——6适配器模式(Adapter)

    6.适配器模式(Adapter) 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题.主要分为三类:类的适配器模式.对象的适配器模式.接口的适配器 ...

  9. C#设计模式(7)——适配器模式(Adapter Pattern)

    一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将"将现存的对象" ...

最新文章

  1. 蓝桥杯 【基础练习】 特殊回文数
  2. Android 有些机型hint不显示
  3. 文本框换行_多行文本框的认识以及代码详解
  4. 哈,又一款超级简单的队列(MQ)实现方案来了~
  5. java成员内部类_Java中的内部类(二)成员内部类
  6. mysql keepalived主从_mysql高可用架构之(一)基于自身主从复制&keepalived实现
  7. ASP.Net数据库如何存取图片
  8. dede织梦调用顶级二级栏目及下三级栏目方法!
  9. Python多线程好文
  10. 农用地包括哪些地类_设施农用地属于什么地类、包括哪些用地?
  11. linux系统如何使用GPT工具进行分区
  12. Vue - 将金额数字转为汉字大写(demo)
  13. Psoc Creator入门——EZI2C 通信
  14. 微信生成二维码 PHP
  15. 高一数学补习可以提高孩子的数学成绩吗?
  16. Android倒计时定时器CountDownTimer的用法
  17. 命令行查看隐藏文件或隐藏文件夹
  18. 汪升华c语言答案,C语言程序设计教程/普通高等教育“十二五”规划教材
  19. 开发登陆按钮(丛林战争项目)
  20. 成都网站建设SEO 成都网站SEO优化方案制作

热门文章

  1. Kali Linux 64位安装WPS
  2. bd9.1 MySQL 常见问题
  3. IntelliJ IDEA 添加本地xsd文件
  4. [UWP小白日记-5]转换MVA学院的XML字幕为SRT
  5. 为打击网络喷子 Instagram禁评论攻击
  6. 使用Jodd简化邮件服务的开发
  7. C# MessageBox 用法大全(转)
  8. vwmare vSphere 4.0产品介绍
  9. CTF---安全杂项入门第三题 这是捕获的黑客攻击数据包,Administrator用户的密码在此次攻击中泄露了,你能找到吗?...
  10. [BZOJ 1014][JSOI2008]火星人prefix(Splay+二分+hash)