文字編輯器 Editor
文字編輯器
題意描述
九發明了一個完美的文字編輯器。這個編輯器擁有兩個游標(cursor),所以九能夠同時在兩處地方插入和刪除文字。這個編輯器除了正常的編輯功能以外,還有一些只有九才知道用處的功能,例如翻轉兩個游標之間的文字。某一天,九把自己的完美文字編輯器給弄丟了,但是她還有好多好多文字需要處理。於是她想請聰明又智慧的你幫她實現完美文字編輯器的一些功能。
功能列表如下:
功能名稱 | 命令格式 | 說明 |
---|---|---|
w 為一個字元,“L”或“R”,表示左游標還是右游標(下同)。該命令將選定游標向左移動,如果已經是最左端則不移動。命令執行成功時輸出“T”,若游標已經在最左端,則輸出“F”。 | ||
w 同上。與< 命令不同的是,該命令將游標向右移動。命令執行成功時輸出“T”,若游標已經在最右端,則輸出“F”。 | ||
I (insert) | I w c | w 同上。c 是一個可見字元(33≤ ascii 碼 ≤ 126),代表在該游標左側插入該字元。該命令始終輸出“T”。 |
D (delete) | D w | w 同上。代表刪除該游標右側的一個字元。命令執行成功時輸出“T”,若游標右側沒有字元輸出“F”。 |
R (reverse) | R | 代表翻轉左游標和右游標之間的字元。該命令只有左游標在右游標左側時才能執行。(兩游標重合時也不能執行)命令執行成功時輸出“T”,否則輸“F”。 |
S (show) | S | 代表顯示當前處理的文字。該命令只輸出文本,不輸出“T”和“F”。 |
開始時文字編輯器中有一定內容,左游標在第一個字元左,右游標在最後一個字元右。
注意:在插入和刪除操作中,沒有被操作的游標與文字的相對左右位置保持不變。特別地,若兩個游標重疊,操作後也仍然重疊。
輸入格式
第一行是初始時文字編輯器內容。
第二行是一個正整數 N,N 表示操作次數。
接下來有 N 行,每行有一個命令,命令格式如上方表格。
輸出格式
對於每個命令,按上方表格要求執行並輸出。
樣例輸入
goodykc
11
I R u
I R l
> L
> L
> L
> L
R
D R
< R
D R
S
樣例輸出
T
T
T
T
T
T
T
F
T
T
goodluck
樣例解釋
[goodykc]
[goodykcu]
[goodykcul]
g[oodykcul]
go[odykcul]
goo[dykcul]
good[ykcul]
good[lucky]
good[lucky](游標右邊沒有字元,失敗刪除)
good[luck]y
good[luck]
goodluck
資料規模與約定
- 對於 40% 的資料:1 ≤ N , 初始文字長度 ≤ 100,資料不包含翻轉(Reverse)操作;
- 另有 30% 的資料:1 ≤ N , 初始文字長度 ≤ 105,資料不包含翻轉(Reverse)操作;
- 另有 20% 的資料:1 ≤ N , 初始文字長度 ≤ 105,資料包含翻轉(Reverse)操作;
- 對於 100% 的資料:1 ≤ N , 初始文字長度 ≤ 4 × 106,輸出檔案大小 ≤ 20MB;
這道題最後3個點難度很大,但是前7個點應該是非常容易通過的,然而我只過了三個,一個原因是對這種程式碼量大的題速度跟不上,還有寫連結串列的時候沒有將頭指標的pre賦為-1,以後寫連結串列的時候一定要注意。
後面3個點的解法還沒看懂,以後再說
更新:其實就是個平衡樹區間翻轉,現在感覺當時的我好 zz 啊
70分程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXL=1e5;
int N;
char s[MAXL+10];
int len;
int tcnt;
struct T{int pre,next;char c;} text[MAXL*11+10];
void del(int x)
{
text[text[x].pre].next=text[x].next;
text[text[x].next].pre=text[x].pre;
text[0].pre=-1;
}
void add(int x,char c)
{
++tcnt;
text[tcnt].pre=x;
text[tcnt].next=text[x].next;
text[text[x].next].pre=tcnt;
text[x].next=tcnt;
text[tcnt].c=c;
text[0].pre=-1;
}
struct C
{
int pos;
void pri(bool t){printf("%s\n",t?"T":"F");}
void move(bool l)
{
if(l)
{
if(text[pos].pre!=-1)
{
pos=text[pos].pre;
pri(true);
}else pri(false);
}else
if(text[pos].next)
{
pos=text[pos].next;
pri(true);
}else pri(false);
}
void insert(char c)
{
add(pos,c);
pos=text[pos].next;
pri(true);
}
void rm()
{
if(text[pos].next)
{
del(text[pos].next);
pri(true);
}else pri(false);
}
} L,R;
int main()
{
freopen("editor.in","r",stdin);
freopen("editor.out","w",stdout);
int i;
scanf("%s",&s);
len=strlen(s);
for(i=0;i<len;i++)
add(i,s[i]);
L.pos=0,R.pos=len;
scanf("%d",&N);
while(N--)
{
char c;
do c=getchar();
while(c<33||c>126);
if(c=='<'||c=='>')
{
bool left=c=='<'?1:0;
do c=getchar(); while(c<33||c>126);
if(c=='L') L.move(left);
else R.move(left);
}else if(c=='I')
{
do c=getchar(); while(c<33||c>126);
if(c=='L')
{
do c=getchar(); while(c<33||c>126);
L.insert(c);
}else
{
do c=getchar(); while(c<33||c>126);
R.insert(c);
}
}else if(c=='D')
{
do c=getchar(); while(c<33||c>126);
if(c=='L') L.rm();
else R.rm();
}else if(c=='S')
{
for(i=text[0].next;i;i=text[i].next)
putchar(text[i].c);
printf("\n");
}
}
return 0;
}
100分標程
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
#define N 10000000
int pre[N], suf[N];
char ch[N], st[N];
int idx, pos[2], cnt[2];
inline void swap(int &a, int &b) {
int c = a;
a = b;
b = c;
}
void Insert(int opt, char c) {
++idx;
ch[idx] = c;
int u = pos[opt], v = suf[u];
pre[idx] = u; suf[idx] = v;
suf[u] = idx; pre[v] = idx;
if (cnt[opt^1] >= cnt[opt]) cnt[opt^1]++;
pos[opt] = idx; cnt[opt]++;
if (pos[opt^1] == u) pos[opt^1] = idx;
puts("T");
}
void LMove(int opt) {
if (pos[opt] == 1) {
puts("F");
return ;
}
int u = pos[opt], v = pre[u];
if (suf[v] != u) swap(suf[v], pre[v]);
pos[opt] = v; cnt[opt]--;
puts("T");
}
void RMove(int opt) {
if (suf[pos[opt]] == 2) {
puts("F");
return ;
}
int u = suf[pos[opt]], v = suf[u];
if (pre[v] != u) swap(suf[v], pre[v]);
pos[opt] = u; cnt[opt]++;
puts("T");
}
void Delete(int opt) {
if (suf[pos[opt]] == 2) {
puts("F");
return ;
}
int u = pos[opt], v = suf[u], w = suf[v];
if (pre[w] != v) swap(suf[w], pre[w]);
if (cnt[opt^1] > cnt[opt]) cnt[opt^1]--;
if (pos[opt^1] == v) pos[opt^1] = u;
suf[u] = w; pre[w] = u;
puts("T");
}
void Reverse() {
if (cnt[1] - cnt[0] <= 0) {
puts("F");
return ;
}
if (cnt[1] - cnt[0] == 1) {
puts("T");
return ;
}
int a = pos[0], b = suf[a], c = pos[1], d = suf[c];
swap(pre[b], suf[b]); swap(pre[c], suf[c]);
suf[a] = c; pre[c] = a; suf[b] = d; pre[d] = b;
pos[1] = b;
puts("T");
}
void Show() {
int u = 1;
while (true) {
if (pre[suf[u]] != u) swap(pre[suf[u]], suf[suf[u]]);
u = suf[u];
if (u == 2) break;
putchar(ch[u]);
}
putchar('\n');
}
void Build() {
scanf("%s",st);
idx = 2;
pre[1] = -1; suf[1] = 2;
pre[2] = 1; suf[2] = -1;
pos[0] = pos[1] = cnt[0] = cnt[1] = 1;
int len = strlen(st);
for (int i = 0; i < len; i++) {
++idx;
ch[idx] = st[i];
pre[idx] = i == 0 ? 1 : idx - 1;
suf[idx] = i == len - 1 ? 2 : idx + 1;
}
if (len > 0) {
suf[1] = 3; pre[2] = idx;
pos[1] = idx; cnt[1] = len + 1;
}
}
inline int Dir() {
getchar();
return getchar() == 'L' ? 0 : 1;
}
int main() {
freopen("editor.in", "r", stdin);
freopen("editor.out", "w", stdout);
Build();
int m;
scanf("%d",&m);
for (int i = 1; i <= m; i++) {
getchar();
char opt = getchar();
while (opt != '<' && opt != '>' && !(opt >= 'A' && opt <= 'Z')) opt = getchar();
if (opt == '<') LMove(Dir());
else if (opt == '>') RMove(Dir());
else if (opt == 'I') {
int d = Dir();
char c = ' ';
while (c < 33 || c > 126) c = getchar();
Insert(d, c);
}
else if (opt == 'D') Delete(Dir());
else if (opt == 'R') Reverse();
else if (opt == 'S') Show();
}
return 0;
}