1. 程式人生 > >例題6-4 破損的鍵盤(又名:悲劇文本)(Broken Keyboard,UVa 11988)—靜態鏈表

例題6-4 破損的鍵盤(又名:悲劇文本)(Broken Keyboard,UVa 11988)—靜態鏈表

else if strlen 靜態鏈表 尾插 指向 第一個元素 內容 其中 分享

問題描述:

你有一個破損的鍵盤。鍵盤上所有的鍵都可以正常工作,但有時候Home鍵或者End鍵會自動按下。你並不知道鍵盤存在這一問題,而是專心打稿子,甚至連顯示器都沒打開。當你打開顯示器後,展現在你面前的是一段悲劇文本。你的任務是在打開顯示器之前計算出這段悲劇文本。

輸入包含多組數據。每組數據占一行,包含不超過100000個字母、下劃線、字符“【”或者“】”。其中字符“【”表示Home鍵,“】”表示End鍵。輸入結束標誌為文件結束符(EOF)。輸入文件不超過5MB。對於每組數據,輸出一行,即屏幕上的悲劇文本。

樣例輸入:

This_is_a_[Beiju]_text

樣例輸出:

BeijuThis_is_a_text

【分析】

1、因為若用數組來保存這段文檔,則太費時間(每輸入一個字符都需要把後面的字符全部右移,給新字符騰出位置)這樣的代碼會超時。

2、所以決定采用靜態鏈表來進行操作,(因為靜態鏈表中有cur指向下一個元素,這樣比較容易操作),為了方便起見,常常在鏈表的第一個元素之前放一個虛擬結點是s[0]。鏈表中插值時采用的尾插入法,比較方便。

3、關於Home與End鍵 從本體的樣例輸出可以看出,本題是需要將[ ]中的內容提到文檔的前面,因為Home表示首位置,End表示末位置 。所以代碼核心就是當讀到 [ 時,給cur賦值0,讀到 ] 時,給cur賦值last,讀到其他字符時,尾插入法插值,cur及last後移。

代碼如下:

#include <cstdio>
#include <cstring>
const int maxn=100000+5;
int last,cur,next[maxn];
char s[maxn];

int main(){
while(scanf("%s",s+1)){
int n=strlen(s+1);//計算字符串s的長度,並賦值給n
last=cur=0;
next[0]=0;//建一個虛擬位置點


for(int i=1;i<=n;i++){
char ch=s[i];
if(ch==‘[‘) cur=0;//因為‘【’代表的home鍵,所以當光標指向【時,cur指針應指向首位置
else if(ch==‘]‘) cur=last;//同上,因為】代表的end鍵,所以當光標指向】時,cur指針應指向末位置
else{//當讀入其他字符時,向靜態鏈表中插值就好
next[i]=next[cur]; next[cur]=i;//尾插入法
if(cur==last) last=i; cur=i;//尾光標向後移動
}
}
//順次輸出
for(int i=next[0];i!=0;i=next[i])
printf("%c",s[i]);
printf("\n");
}
return 0;
}

運行結果:

技術分享

總結:

1、在剛開始看到這道題的時候,因為不了解Home鍵和End鍵的具體功能,對代碼中部的cur與last賦值不是很明白,在嘗試之後,才理解為何Home給cur賦0,End給cur賦last;

2、看到strlen函數的時候,不太明白他表示的意思,去百度時看見有的代碼的註釋寫的為 初始化鏈表(更加懵逼臉),在仔細百度strlen後。。一個計算字符串長度的函數(不包括

‘\0‘) 用到此處的目的是為了要計算出 s鏈表中存儲的字符串的長度,便於之後for循環時的需要

例題6-4 破損的鍵盤(又名:悲劇文本)(Broken Keyboard,UVa 11988)—靜態鏈表