1. 程式人生 > >UVa 11988 Broken Keyboard (a.k.a. Beiju Text) (連結串列)

UVa 11988 Broken Keyboard (a.k.a. Beiju Text) (連結串列)

      Broken Keyboard (a.k.a. Beiju Text)
You're typing a long text with a broken keyboard. Well it's not so badly broken. The only problem with the keyboard is that sometimes the "home" key or the "end" key gets automatically pressed (internally).
You're not aware of this issue, since you're focusing on the text and did not even turn on the monitor! After you finished typing, you can see a text on the screen (if you turn on the monitor).
In Chinese, we can call it Beiju. Your task is to find the Beiju text.

Input
There are several test cases. Each test case is a single line containing at least one and at most 100,000 letters, underscores and two special characters '[' and ']'. '[' means the "Home" key is pressed internally, and ']' means the "End" key is pressed internally. The input is terminated by end-of-file (EOF). The size of input file does not exceed 5MB.

Output

For each case, print the Beiju text on the screen.


Sample Input
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University

Output for the Sample Input
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University


題目大意:你在輸入文章的時候,鍵盤上的Home鍵和End鍵出了問題,會不定時的按下。給你一段按鍵的文字,其中'['表示Home鍵,']'表示End鍵,輸出這段悲劇的文字。

思路:使用連結串列來模擬,遇到Home鍵,就將後邊的文字插入到這段文字的最前邊,遇到End鍵,就插入到這段文字的最後邊。但是用連結串列會用到指標,過程比較繁瑣。這裡用一個Next陣列模擬指向,Next[i]表示當前顯示屏中s[i]右邊的字元下標。再用一個cur表示當前游標的位置,last表示最後一個字元的記錄位置,這樣遇到End鍵,就能直接找到游標下一個指向的字元位置了。

#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 100005;
char s[maxn];
int next[maxn];
int cur,last;

int main(int argc, char const *argv[])
{
	while(scanf("%s",s+1) != EOF)
	{
		int len = strlen(s+1);
		cur = last = 0;
		next[0] = 0;

		for(int i = 1;i <= len;i++)
		{
			char ch = s[i];
			if(ch == '[')
				cur = 0;
			else if(ch == ']')
				cur = last;
			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;
}

在CSDN上看到有一個人用雙端佇列做的,感覺思路很是精妙。首先他將第一個非 '['、']' 的字元下標 (亦是地址) 插入隊首,然後遇到 '[' 時將下一個字元的下標插入隊首,遇到 ']' 時將下一個字元的下標插入隊尾,同時將 '[' 和 ']' 都置為 '\0' 方便輸出。
#include <cstdio>
#include <queue>
using namespace std;

const int maxn = 100010;
char str[maxn];

int main(int argc, char const *argv[])
{
	while(~scanf("%s",str))
	{
		deque<int> q;
		int i = 0;
		while(str[i] == '[' || str[i] == ']')
			i++;
		q.push_front(i);
		while(str[i] != '\0')
		{
			if(str[i] == '[')
			{
				q.push_front(i+1);
				str[i] = '\0';
			}
			else if(str[i] == ']')
			{
				q.push_back(i+1);
				str[i] = '\0';
			}
			i++;
		}

		while(!q.empty())
		{
			printf("%s",str+q.front());
			q.pop_front();
		}
		printf("\n");
	}
	return 0;
}