链表的使用

链表的使用

(本文仅为笔者学习笔记,如有错误之处恳请各位读者指正)


简译:
         你有一个破损的键盘。键盘上的所有键都可以正常工作,但有时Home键或者End键会自动按下。你并不知道键盘存在这一问题,而是专心地打稿子,甚至连显示器都没打开。当你打开显示器之后,展现在你面前的是一段悲剧的文本。你的任务是在打开显示器之前计算出这段悲剧文本。
         输入包含多组数据。每组数据占一行,包含不超过100000个字母、下划线、字符"["或"]"。其中字符"["表示Home键,"]"表示End键。输入结束标志为文件结束符(EOF)。输入文件不超过5MB。对于每组数据,输出一行,即屏幕上的悲剧文本。
分析:
         设输入的字符串是s[1~n],则可以用s[next[i]]表示在显示器中紧接着字符s[i]的下一个字符。将整个字符串看作一个链表,next[i]可以看作字符i的next指针。

(以下程序中只是在数组上模拟链表操作,并非真正意义上的链表)
#include<cstdio>
#include<cstring>
const int maxn = 100000+5;
int last;  // last:链表尾指针 
int cur;   // 指向当前字符的前一个字符 
int next[maxn];  // 记录链表中各个节点的后继节点(s数组中的下标)
char s[maxn];  // 文本数组


int main(){
	while(scanf("%s", s+1) == 1){  // 有文本输入 
		int n = strlen(s+1);  // s+1:输入保存在s[1],s[2]...中
		last = cur = 0;  // 初始化链表的尾指针和cur指针(均指向头部虚拟节点) 
		next[0] = 0;
		
		for(int i=1; i<=n; i++){  // i:当前节点 
			char ch = s[i];  // 一次读取输入文本中的每个字符
			if(ch == '[')  // 碰到home键 
			    cur = 0;   // cur回到头节点继续写 
			else if(ch == ']')  // 碰到end键
			    cur = last;   // cur回到尾部节点继续写 
			else{
				// 第一层循环:         next[i=1]=next[cur=0]=0;     next[cur=0]=1;
				// 第二层循环:          next[i=2]=next[cur=1]=0;     next[cur=1]=2;
				// next[当前字符节点]=next[cur上一个字符节点]=0;    next[cur上一个字符节点]=当前字符节点 
				next[i] = next[cur];  // 将当前节字符点的next指针暂时指向头结点
				next[cur] = i;  // 将上一个字符节点的next指针指向当前字符节点 
				
				if(cur == last)  // 更新尾指针
				    last = i;
				cur = i;  // cur指向当前字符,进入下一层循环后i+1,cur又指向了"前一个字符" 
			} 
		} 
		for(int i=next[0]; i!=0; i=next[i]){  // 按照next记录的后继节点在s数组中的下标依次输出文本中的字符 
			printf("%c",s[i]);
		} 
		printf("\n");
	}
	return 0;
} 

题目连接:Broken Keyboard(a.k.a. Beiju Text) - UVa 11988
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值