1. 程式人生 > >文字編輯器 Editor

文字編輯器 Editor

文字編輯器

題意描述

九發明了一個完美的文字編輯器。這個編輯器擁有兩個游標(cursor),所以九能夠同時在兩處地方插入和刪除文字。這個編輯器除了正常的編輯功能以外,還有一些只有九才知道用處的功能,例如翻轉兩個游標之間的文字。某一天,九把自己的完美文字編輯器給弄丟了,但是她還有好多好多文字需要處理。於是她想請聰明又智慧的你幫她實現完美文字編輯器的一些功能。
功能列表如下:

功能名稱 命令格式 說明
< (move left) < w w 為一個字元,“L”或“R”,表示左游標還是右游標(下同)。該命令將選定游標向左移動,如果已經是最左端則不移動。命令執行成功時輸出“T”,若游標已經在最左端,則輸出“F”。
> (move right) > w 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;
}