「Editor」
November 8, 2018
Assuming that the string is initially empty, the basic operations that can be performed are append/insert/delete/replace, as described below:
append: Appends a string of the specified length to the string.
insert: Inserts a string of the specified length at the specified position of an existing string.
delete: Removes a specified length of characters from an existing string at a specified location.
replace: Replaces a number of characters at a specified position in an existing string with another string.
字符串的位置从 1 开始计数
字符串中的字符,只能是 a-z、A-Z、0-9
每行由一个基本操作+后续参数组成,每种操作的参数不同,用冒号分隔
append:两个参数,分别是要追加字符串的长度、具体的字符串内容
insert:三个参数,分别是插入位置、要插入字符串的长度、具体的内容
delete:两个参数,分别是删除位置,要删除的字符个数
replace:四个参数,分别是替换位置,被替换长度,替换长度,具体的内容
样例:
append : 12 : abcdefghijkl # 操作完成后,字符串为 "abcdefghijkl" append : 10 : ABCDEFGHIJ # 操作完成后,字符串为 "abcdefghijklABCDEFGHIJ" #insert : 9 : 2 : pq # 本行忽略(忽略#开头的行) insert : 2 : 3 : XYZ # 操作完成后,字符串为 "aXYZbcdefghijklABCDEFGHIJ" delete : 10 : 2 # 操作完成后,字符串为 "aXYZbcdefijklABCDEFGHIJ" replace : 7 : 3 : 10 : 0123456789 # 操作完成后,字符串为 "aXYZbc0123456789ijklABCDEFGHIJ"
代码:
块状链表随便乱搞了一下就好了
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cctype>
#include <cstring>
#include <string>
#define MAXIN 1
#define gc() (SS == TT && (TT = (SS = IN) + fread(IN,1,MAXIN,stdin),SS == TT) ? -1 : *SS++)
int N, qqq;
const int M = 1024 * 1024 * 1 + 5;
int maxsize = 40000, maxnum;
int num, *next, *sz, *pool;
char **data, str[M], IN[MAXIN], *SS = IN, *TT = IN;
char *pre;
inline int read()
{
int now = 0, f = 1;
register char c = gc();
for (; !isdigit(c); c = gc())
if (c == '-')
f = -1;
for (; isdigit(c);
now = now * 10 + c - '0', c = gc());
return now * f;
}
inline int new_block()
{
return pool[++num];
}
inline void del_block(int v)
{
pool[num--] = v;
}
void init()
{
for (int i = 1; i < maxnum; ++i)
pool[i] = i;
sz[0] = 0; //新建一个0节点,方便 表头就是0
next[0] = -1;
}
void merge(int cur, int Next)
{
memcpy(data[cur] + sz[cur], data[Next], sz[Next]);
next[cur] = next[Next];
sz[cur] += sz[Next];
del_block(Next);
}
void maintain()
{
for (int cur = 0, Next = next[0]; ~cur; cur = next[cur], Next = next[cur])
while ((~Next) && sz[cur] + sz[Next] <= maxsize)
{
merge(cur, Next);//最好不用next[Next],因为已经合并、删掉了
Next = next[cur];
}
}
int get_index(int &pos) //找到pos所在的块,并将pos定位为块内位置
{
int cur = 0;
while ((~cur) && pos > sz[cur]) //把cur定位到某一块的末尾,不用下一块开头了(pos>=sz)
{
pos -= sz[cur];
cur = next[cur];
}
return cur;
}
void update(int cur, int Next, int len, char *s)//给新的块Next设置数据及指针
{
next[Next] = next[cur];
next[cur] = Next;
sz[Next] = len;
memcpy(data[Next], s, len);
}
void split(int cur, int pos)
{
if (cur == -1 || pos == sz[cur])//不能判!pos 因为后边会直接用next[cur],不分裂会跳过该块
return;
int Next = new_block();
update(cur, Next, sz[cur] - pos, data[cur] + pos);
sz[cur] = pos;
}
void insert(int pos, int len)
{
int cur = get_index(pos), sum = 0, Next;
split(cur, pos);
while (sum + maxsize <= len)
{
Next = new_block();
update(cur, Next, maxsize, str + sum);//先分成尽可能多的整块
sum += maxsize;
cur = Next;
}
if (len - sum) //剩余的单独放到一块
Next = new_block(), update(cur, Next, len - sum, str + sum);
maintain();
}
void erase(int pos, int len)
{
int cur = get_index(pos), Next;
split(cur, pos);
Next = next[cur]; //because of here
while ((~Next) && len > sz[Next])
len -= sz[Next], del_block(Next), Next = next[Next];
split(Next, len);
del_block(Next), next[cur] = next[Next];
maintain();
}
void get_data(int pos, int len)
{
delete[]pre;
int cur = get_index(pos), sum = sz[cur] - pos;
if (len < sum)
sum = len;
//memcpy(str, data[cur] + pos, sum);
fwrite(data[cur] + pos, sizeof(char), sum, stdout);
cur = next[cur];
while ((~cur) && sum + sz[cur] <= len)
{
//memcpy(str + sum, data[cur], sz[cur]);
fwrite(data[cur], sizeof(char), sz[cur], stdout);
sum += sz[cur];
cur = next[cur];
}
if ((~cur) && len - sum)
fwrite(data[cur], sizeof(char), len - sum, stdout);
//memcpy(str + sum, data[cur], len - sum);
//str[len] = '\0';
//printf("%s", str);
}
bool alloc(int size)
{
next = new(std::nothrow) int[size];
if (next == NULL)
return false;
sz = new(std::nothrow) int[size];
if (sz == NULL)
return false;
pool = new(std::nothrow) int[size];
if (pool == NULL)
return false;
data = new(std::nothrow) char*[size];
if (data == NULL)
return false;
for (int i = 0; i < size; ++i)
{
data[i] = new(std::nothrow) char[maxsize];
qqq = i;
if (data[i] == NULL)
return false;
}
return true;
}
int main()
{
freopen("input.txt", "rb", stdin);
freopen("output.txt", "wb", stdout);
fseek(stdin, 0L, SEEK_END);
N = ftell(stdin);
fseek(stdin, 0L, SEEK_SET);
maxnum = N * 2 / maxsize + 100;
pre = new(std::nothrow) char[M];
int left = 1, right = maxnum, mid = (left + right) / 2;
while (1)
{
if (left == mid || right == mid)
{
maxnum = mid;
break;
}
if (alloc(mid) == true)
{
delete[]next;
delete[]sz;
delete[]pool;
for (int i = 0; i < mid; ++i)
delete[]data[i];
delete[]data;
left = mid;
mid = (left + right) / 2;
}
else
{
delete[]next;
delete[]sz;
delete[]pool;
for (int i = 0; i < qqq; ++i)
delete[]data[i];
delete[]data;
right = mid;
mid = (left + right) / 2;
}
}
alloc(maxnum);
int limit;
if (maxnum > 200)
limit = (maxnum - 100)*maxsize / 2;
else
limit = 100 * maxsize / 2;
init();
int pos = 0, len, tot = 0;
char c;
while (1)
{
c = gc();
if (c == -1)
break;
if (c == 'a')
{
len = read();
if (len + tot > limit)
{
get_data(0, tot);
return 0;
}
while (1)
{
char ch = gc();
if (isdigit(ch) || islower(ch) || isupper(ch))
{
str[0] = ch;
break;
}
}
fread(str + 1, sizeof(char)*(len - 1), 1, stdin);
insert(tot, len);
tot += len;
//get_data(0, tot);
while (gc() != '\n')
;
}
else if (c == 'i')
{
pos = read();
len = read();
if (len + tot > limit)
{
get_data(0, tot);
return 0;
}
while (1)
{
char ch = gc();
if (isdigit(ch) || islower(ch) || isupper(ch))
{
str[0] = ch;
break;
}
}
fread(str + 1, sizeof(char), len - 1, stdin);
insert(pos - 1, len);
tot += len;
//get_data(0, tot);
while (gc() != '\n')
;
}
else if (c == 'd')
{
pos = read();
len = read();
erase(pos - 1, len);
tot -= len;
//get_data(0, tot);
}
else if (c == 'r')
{
pos = read();
len = read();
erase(pos - 1, len);
tot -= len;
len = read();
if (len + tot > limit)
{
get_data(0, tot);
return 0;
}
tot += len;
while (1)
{
char ch = gc();
if (isdigit(ch) || islower(ch) || isupper(ch))
{
str[0] = ch;
break;
}
}
fread(str + 1, sizeof(char), len - 1, stdin);
insert(pos - 1, len);
//get_data(0, tot);
while (gc() != '\n')
;
}
else if (c == '#')
while (gc() != '\n')
;
}
get_data(0, tot);
fclose(stdout);
fclose(stdin);
return 0;
}