【POJ2887】【块状链表】Big String
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:
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 POJ Monthly--2006.07.30, zhucheng
|
【分析】
知识拿块状链表练练手而已。
这是我写的第一个块状链表,怎么说呢,块状链表应该说是写起来比较麻烦的,因为要注意的边界条件有点多,不过适应了应该会很好骗分。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #include <utility> 7 #include <iomanip> 8 #include <string> 9 #include <cmath> 10 #include <queue> 11 #include <map> 12 13 const int MAXC = 1000000 + 10; 14 const int MAXM = 1000 + 10; 15 const int MAXN = 1000000 + 10; 16 const int N=2000, L=2000;//L代表单个块的长度,N为最大的总块数 17 using namespace std; 18 struct Block_List {//BLOCK_LIST为块状链表的英文名 19 struct Node { 20 char str[L]; 21 //next数组志向下一个块状链表 22 int next, size; 23 void init(){ 24 memset(str, 0, sizeof(str)); 25 next = -1; 26 size = 0; 27 } 28 }list[N]; 29 int head, tot; 30 31 void init(char str[]){ 32 head = tot = 0;//整个块状链表进行初始化 33 list[tot++].init();//进行第一个块状链表的初始化 34 for (int i = 0, cur = head; str[i]; cur = list[cur].next){ 35 for (int j = 0; j < L && str[i]; j++, i++){ 36 list[cur].str[j] = str[i]; 37 list[cur].size++; 38 } 39 //还能继续装 40 if (str[i]){ 41 list[tot].init();//注意tot永远指向下一个空的块状链表 42 list[cur].next = tot++; 43 } 44 } 45 for (int cur = head; cur != -1; cur = list[cur].next) 46 if (list[cur].size == L) split(cur);//分割块状链表 47 } 48 //对第x块块状链表进行分割 49 void split(int x){ 50 list[tot].init(); 51 //注意块状链表的下标是从0 - (L - 1) 52 for (int i = L / 2; i < L; i++){ 53 list[tot].str[i - L/2] = list[x].str[i]; 54 list[tot].size++; 55 list[x].size--; 56 list[x].str[i] = 0;//清空?好像没什么用 57 } 58 list[tot].next = list[x].next; 59 list[x].next = tot++; 60 } 61 void insert(int pos, char val){ 62 int cur = head; 63 //注意开始不需要-1是因为一定成立,注意不要让任何一个块状链表达到满的状态,不然维护起来很麻烦 64 while (pos - list[cur].size > 0 && list[cur].next != -1){ 65 pos -= list[cur].size; 66 cur = list[cur].next; 67 } 68 if (pos >= list[cur].size) list[cur].str[list[cur].size] = val; 69 else { 70 //先进行移动 71 for (int i = list[cur].size; i > pos; i--) list[cur].str[i] = list[cur].str[i - 1] ; 72 list[cur].str[pos] = val; 73 } 74 list[cur].size++; 75 if (list[cur].size == L) split(cur); 76 } 77 char find(int pos){ 78 int cur = head; 79 while ( pos - list[cur].size > 0){ 80 pos -= list[cur].size; 81 cur = list[cur].next; 82 } 83 return list[cur].str[pos - 1];//注意要-1 84 } 85 }A; 86 char str[MAXN]; 87 int n; 88 89 int main() { 90 #ifdef LOCAL 91 freopen("data.txt", "r", stdin); 92 freopen("out.txt", "w", stdout); 93 #endif 94 scanf("%s%d", str, &n); 95 A.init(str);//初始化块状链表 96 for (int i = 0; i < n; i++){ 97 int pos; 98 scanf("%s", str); 99 if (str[0] == 'I'){//插入单个的单词 100 char S[2]; 101 scanf("%s%d", S, &pos); 102 A.insert(pos - 1, S[0]); 103 } else { 104 scanf("%d", &pos); 105 printf("%c\n", A.find( pos )); 106 } 107 } 108 return 0; 109 }