例题6-4 破损的键盘 UVa11988

1.题目描述:点击打开链接

2.解题思路:本题利用链表解决。每输入一个字符,就把它存起来,设输入字符串是s[1...n],则可以用Next[i]表示在当前显示屏中s[i]右边的字符编号。为了便于后续处理,假设s的最前面还有一个虚拟的s[0](这是链表的常用处理方式,请务必牢记),那么Next[0]就表示显示屏中最左边的字符,再用一个变量cur表示光标位置:即当前光标位于s[cur]的右边(即我们的DOS窗口中经常出现的下一个待输入的位置)。cur=0说明光标位于s[0]的右边,即显示屏的最左边。为了移动光标,还需要一个变量last表示显示屏的最后一个字符是s[last]。

接下来考虑如何用链表来实现本题。最初我们需要一个头结点,不妨将它设为0,即Next[0]=0。头结点只是起到一个标记的作用,不表示真实的位置。链表中的头结点总是指向链表的第一个元素。然后开始插入元素。链表中插入元素就两句代码:Next[i]=head;head=i。第一句表示新元素i的下一个元素指向当前head指向的元素,第二句话是更新head的指向,指向新的第一个元素i。当所有元素插入完毕后,只需要从头结点开始,顺着Next数组即可按顺序输出整个链表。注意,这样的插入实际上是在尾部插入,链表的尾部在不断地变长。这道题中用cur来当做头结点,通过移动头结点的位置即可实现在链表的不同位置插入新元素。根据题意,当遇到‘['时,头结点变为0,遇到‘]'时,头结点变为last即可。详细过程见代码注释。

3.代码:

#define _CRT_SECURE_NO_WARNINGS 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define N 100000+5
int last, cur, Next[N];
char s[N];
int main()
{
	//freopen("t.txt", "r", stdin);
	while (~scanf("%s", s + 1))
	{
		int n = strlen(s + 1);
		last = cur = 0;
		Next[0] = 0;
		for (int i = 1; i <= n; i++)
		{
			char ch = s[i];
			if (ch == '[')cur = 0;//头结点移到位置0
			else if (ch == ']')cur = last;//头结点移到位置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]);
		cout << endl;
	}
	return 0;
}

你可能感兴趣的:(算法竞赛入门经典(第二版),数据结构——链表)