Noi-03-editor

文本编辑器

【问题描述】

很久很久以前,DOS3.x的程序员们开始对EDLIN感到厌倦。于是,人们开始纷纷改用自己写的文本编辑器……

多年之后,出于偶然的机会,小明找到了当时的一个编辑软件。进行了一些简单的测试后,小明惊奇地发现:那个软件每秒能够进行上万次编辑操作(当然,你不能手工进行这样的测试)!于是,小明废寝忘食地想做一个同样的东西出来。你能帮助他吗?

 

为了明确任务目标,小明对“文本编辑器”做了一个抽象的定义:

文本:由0个或多个字符构成的序列。这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格。

光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。

文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下六条操作的程序。如果这段文本为空,我们就说这个文本编辑器是空的。

 

操作名称

输入文件中的格式

功能

MOVE(k)

Move k

将光标移动到第k个字符之后,如果k=0,将光标移到文本第一个字符之前

INSERT(n, s)

Insert n¿

S

在光标后插入长度为n的字符串s,光标位置不变,n ³ 1

DELETE(n)

Delete n

删除光标后的n个字符,光标位置不变,n ³ 1

GET(n)

Get n

输出光标后的n个字符,光标位置不变,n ³ 1

PREV()

Prev

光标前移一个字符

NEXT()

Next

光标后移一个字符

 

比如从一个空的文本编辑器开始,依次执行操作INSERT(13, “Balanced□tree”),MOVE(2),DELETE(5),NEXT(),INSERT(7, “□editor”),MOVE(0),GET(15)后,会输出“Badeditortree”,如下表所示:

 

操作

操作前的文本

操作后的结果

INSERT(13, “Balancedtree)

|

(只有光标,文本为空)

|Balancedtree

MOVE(2)

|Balancedtree

Ba|lancedtree

DELETE(5)

Ba|lancedtree

Ba|dtree

NEXT()

Ba|dtree

Bad|□tree

INSERT(7, “□editor)

Bad|□tree

Bad|□editortree

MOVE(0)

Bad|□editortree

|Badeditortree

GET(15)

|Badeditortree

输出“Badeditortree

上表中,“|”表示光标,“□”表示空格。

 

你的任务是:

l        建立一个空的文本编辑器。

l        从输入文件中读入一些操作指令并执行。

l        对所有执行过的GET操作,将指定的内容写入输出文件。

【输入文件】

输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作。其中:

为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例)。

除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。

 

这里我们有如下假定:

l        MOVE操作不超过50000个,INSERT和DELETE操作的总个数不超过4000,PREV和NEXT操作的总个数不超过200000。

l        所有INSERT插入的字符数之和不超过2M(1M=1024*1024),正确的输出文件长度不超过3M字节。

l        DELETE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作不会把光标移动到非法位置。

l        输入文件没有错误。

 

对C++选手的提示:经测试,对最大的测试数据使用fstream进行输入有可能会比使用stdio慢约1秒,因此建议在可以的情况下使用后者。

【输出文件】

输出文件editor.out的每行依次对应输入文件中每条GET指令的输出。

【样例输入】

15

Insert 26

abcdefghijklmnop

qrstuv wxy

Move 16

Delete 10

Move 5

Insert 1

^

Next

Insert 1

_

Next

Next

Insert 4

.\/.

Get 4

Prev

Insert 1

^

Move 0

Get 22

【样例输出】

.\/.

abcde^_^f.\/.ghijklmno


-------------------------------------------------------------------------------------------------------------------
典型的数据结构题,官方的做法是采用可密集检索的双向链表,想一想编程复杂度我就已经恶心了,但还是硬着头皮写了下来,两个半小时,成功Ac。(ps:代码200+,头疼啊)
-------------------------------------------------------------------------------------------------------------------
代码:
program editor;
const
     step=100;
type
    link=^node;
    node=record
                left,right,hleft,hright:link;
                data:char;
               end;
var
   at,now:longint;
   pat:link;
function newlink(ch:char):link;
var
   p:link;
begin
     new(p);
     with p^ do begin
          left:=nil;
          right:=nil;
          hleft:=nil;
          hright:=nil;
          data:=ch;
     end;
end;
procedure init;
begin
     at:=0;
     now:=0;
     pat:=newlink('#');
end;
procedure move(now:longint);
begin
     if at<now then begin
        while at+step<=now do begin
              pat:=pat^.hright;
              inc(at,step);
        end;
        while at+1<=now do begin
              pat:=pat^.right;
              inc(at);
        end;
     end;
     if at>now then begin
        while at-step>=now do begin
              pat:=pat^.hleft;
              dec(at,step);
        end;
        while at-1>=now do begin
              pat:=pat^.left;
              dec(at);
        end;
     end;
end;
procedure scan(n:longint;var h,t:link);
var
   ch:char;
   p:link;
   i:longint;
begin
     i:=1;
     while i<=n do begin
           read(ch);
           if (ord(ch)>=32)and(ord(ch)<=126) then begin
              if i=1 then begin
                 h:=newlink(ch);
                 t:=h;
              end else begin
                  p:=newlink(ch);
                  p^.left:=t;
                  t^.right:=p;
                  t:=p;
              end;
              inc(i);
           end;
     end;
     readln;
end;
procedure insert(n:longint);
var
   h,t,pleft,pright:link;
   ileft,iright:longint;
begin
     move(now);
     scan(n,h,t);
     t^.right:=pat^.right;
     if pat^.right<>nil then pat^.right^.left:=t;
     h^.left:=pat;
     pat^.right:=h;
     ileft:=now;
     pleft:=pat;
     while (now-ileft+1<step)and(pleft^.left<>nil) do begin
           dec(ileft);
           pleft:=pleft^.left;
     end;
     iright:=now;
     pright:=pat;
     while ((iright-ileft)<step)and(pright<>nil) do begin
           inc(iright);
           pright:=pright^.right;
     end;
     while ileft<=now+n do begin
           pleft^.hright:=pright;
           if pright<>nil then begin
              pright^.hleft:=pleft;
              pright:=pright^.right;
           end;
           pleft:=pleft^.right;
           inc(ileft);
     end;
end;
procedure delete(n:longint);
var
   pleft,pright:link;
   ileft,iright:longint;
begin
     move(now);
     while n>0 do begin
           pat^.right:=pat^.right^.right;
           dec(n);
     end;
     if pat^.right<>nil then pat^.right^.left:=pat;
     ileft:=now;
     pleft:=pat;
     while (now-ileft+1<step)and(pleft^.left<>nil) do begin
           dec(ileft);
           pleft:=pleft^.left;
     end;
     iright:=now;
     pright:=pat;
     while (iright-ileft<step)and(pright<>nil) do begin
           inc(iright);
           pright:=pright^.right;
     end;
     while ileft<=now do begin
           pleft^.hright:=pright;
           if pright<>nil then begin
              pright^.hleft:=pleft;
              pright:=pright^.right;
           end;
           inc(ileft);
           pleft:=pleft^.right;
     end;
     
end;
procedure get(n:longint);
var
   p:link;
begin
     move(now);
     p:=pat^.right;
     while n>0 do begin
           write(p^.data);
           dec(n);
           p:=p^.right;
     end;
     writeln;
end;
procedure prev;
begin
     dec(now);
end;
procedure next;
begin
     inc(now);
end;
procedure debug;
var
   p:link;
begin
     writeln('Debug:');
     p:=pat;
     while p^.left<>nil do p:=p^.left;
     while p<>nil do begin
           write('Data:<',p^.data,'>');
           if p^.hleft<>nil then
               write(#32,'Hleft:<',p^.hleft^.data,'>')
           else
               write(#32,'Hleft:<#>');
           if p^.hright<>nil then
               write(#32,'Hright:<',p^.hright^.data,'>')
           else
               write(#32,'Hright:<#>');
           if p=pat then write(#32,'<pat>');
           writeln;
           p:=p^.right;
     end;
     writeln;
end;
procedure process;
var
   command:string;
   n,T,code:longint;
begin
     init;
     readln(T);
     while T>0 do begin
           dec(T);
           readln(command);
           if command[1]='M' then begin
              val(copy(command,6,length(command)-5),n,code);
              now:=n;
           end;
           if command[1]='I' then begin
              val(copy(command,8,length(command)-7),n,code);
              insert(n);
           end;
           if command[1]='D' then begin
              val(copy(command,8,length(command)-7),n,code);
              delete(n);
           end;
           if command[1]='G' then begin
              val(copy(command,5,length(command)-4),n,code);
              get(n);
           end;
           if command[1]='P' then prev;
           if command[1]='N' then next;

           //debug;
     end;
end;
begin
     assign(input,'editor.in');
     assign(output,'editor.out');
     reset(input);
     rewrite(output);
     
     process;
     
     close(input);
     close(output);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值