【POJ2887】【块状链表】Big String

【POJ2887】【块状链表】Big String

转载自:http://www.cnblogs.com/hoskey/p/4322417.html

Description

You are given a string and supposed to do some string manipulations.

Input

The first line of the input contains the initial string. You can assume that it is non-empty and its length does not exceed 1,000,000.

The second line contains the number of manipulation commands N (0 < N ≤ 2,000). The following N lines describe a command each. The commands are in one of the two formats below:

  1. I ch p: Insert a character ch before the p-th character of the current string. If p is larger than the length of the string, the character is appended to the end of the string.
  2. Q p: Query the p-th character of the current string. The input ensures that the p-th character exists.

All characters in the input are digits or lowercase letters of the English alphabet.

Output

For each Q command output one line containing only the single character queried.

Sample Input

ab
7
Q 1
I c 2
I d 4
I e 2
Q 5
I f 1
Q 3

Sample Output

a
d
e

Source

【分析】

知识拿块状链表练练手而已。

这是我写的第一个块状链表,怎么说呢,块状链表应该说是写起来比较麻烦的,因为要注意的边界条件有点多,不过适应了应该会很好骗分。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <map>

const int MAXC = 1000000 + 10; 
const int MAXM = 1000 + 10; 
const int MAXN = 1000000 + 10;
const int N=2000, L=2000;//L代表单个块的长度,N为最大的总块数 
using namespace std;
struct Block_List {//BLOCK_LIST为块状链表的英文名 
    struct Node {
        char str[L];
        //next数组志向下一个块状链表 
        int next, size;
        void init(){
             memset(str, 0, sizeof(str));
             next = -1;
             size = 0;
        }
    }list[N];
    int head, tot;

    void init(char str[]){
         head = tot = 0;//整个块状链表进行初始化
         list[tot++].init();//进行第一个块状链表的初始化
         for (int i = 0, cur = head; str[i]; cur = list[cur].next){
             for (int j = 0; j < L && str[i]; j++, i++){
                 list[cur].str[j] = str[i];
                 list[cur].size++;
             }
             //还能继续装 
             if (str[i]){
                list[tot].init();//注意tot永远指向下一个空的块状链表
                list[cur].next = tot++; 
             }
         } 
         for (int cur = head; cur != -1; cur = list[cur].next)
         if (list[cur].size == L) split(cur);//分割块状链表 
    }
    //对第x块块状链表进行分割 
    void split(int x){
         list[tot].init();
         //注意块状链表的下标是从0 - (L - 1) 
         for (int i = L / 2; i < L; i++){
             list[tot].str[i - L/2] = list[x].str[i];
             list[tot].size++;
             list[x].size--;
             list[x].str[i] = 0;//清空?好像没什么用 
         }
         list[tot].next = list[x].next;
         list[x].next = tot++;
    }
    void insert(int pos, char val){
         int cur = head;
         //注意开始不需要-1是因为一定成立,注意不要让任何一个块状链表达到满的状态,不然维护起来很麻烦 
         while (pos - list[cur].size > 0 && list[cur].next != -1){
               pos -= list[cur].size;
               cur = list[cur].next; 
         }
         if (pos >= list[cur].size) list[cur].str[list[cur].size] = val;
         else {
              //先进行移动
              for (int i = list[cur].size; i > pos; i--) list[cur].str[i] = list[cur].str[i - 1] ;
              list[cur].str[pos] = val;
         }
         list[cur].size++;
         if (list[cur].size == L) split(cur);
    }
    char find(int pos){
         int cur = head;
         while ( pos - list[cur].size > 0){
               pos -= list[cur].size;
               cur = list[cur].next;
         }
         return list[cur].str[pos - 1];//注意要-1 
    }
}A;
char str[MAXN];
int n;

int main() {
    #ifdef LOCAL
    freopen("data.txt",  "r",  stdin);
    freopen("out.txt",  "w",  stdout); 
    #endif
    scanf("%s%d", str, &n);
    A.init(str);//初始化块状链表
    for (int i = 0; i < n; i++){
        int pos;
        scanf("%s", str);
        if (str[0] == 'I'){//插入单个的单词 
           char S[2]; 
           scanf("%s%d", S, &pos);
           A.insert(pos - 1, S[0]);
        } else {
           scanf("%d", &pos);
           printf("%c\n", A.find( pos ));
        }
    } 
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值