UVa11988:破损的键盘(悲剧文本)【Java】

题目:

       你有一个破损的键盘。键盘上所有的键都可以正常工作,但有时候Home键或者End键会自动按下。你并不知道键盘存在这一问题,而是专心打稿子,甚至连显示器都没打开。当你打开显示器后,展现在你面前的是一段悲剧文本。你的任务是在打开显示器之前计算出这段悲剧文本。

       输入包含多组数据。每组数据占一行,包含不超过100000个字母、下划线、字符“[”或者“]”。其中字符“[”表示Home键,“]”表示End键。输入结束标志为文件结束符(EOF)。输入文件不超过5MB。对于每组数据,输出一行,即屏幕上的悲剧文本。

输入:

This_is_a_[Beiju]_text

[[]][][]Happy_Birthday_to_Tsinghua_University

输出:

BeijuThis_is_a_text

Happy_Birthday_to_Tsinghua_University

分析:

      对于此题,可引入一个变量来保存字符输入的光标位置,根据我们的日常输入习惯可知,改变光标位置时,每个字符都会进行移动。而题目中有每行输入的数据“包含不超过100000个字符”的条件,显然字符数量较为庞大,不适合使用数组求解,因为数组元素为顺序存储,在数组某个位置插入新元素时,会导致大量的数据移动,效率低,耗时大,不适合用于此题的求解。

      链表相对数组而言,在数据的移动方面有着很大优势,因此,本题采用链表的存储方式求解。

   (注:并非引入真正的链表,而是采用链表的思想,引入两个数组分别作为链表的数据域和指针域)

package uva;
import java.util.*;
public class Uva11988 {
	public static void main(String[] args){
		//题目说明每行输入字符数目不超过100000个,故加5防止超出
		int maxn = 100000+5;
		//last输入字符串的最后一个字符后面的位置
		//cur表示光标的当前位置
		//next[]在这里相当于链表的指针域
		int last, cur, next[];
		next = new int [maxn];
		//s[]数组相当于链表的数据域
		char s[] =new char[maxn];
		//s[0]相当于链表的头结点,不存放数据
		s[0] = 0;
		//字符串str起缓冲作用,Java语言无法直接从键盘输入char型数据
		String str;
		Scanner sc = new Scanner (System.in);
		while(sc.hasNext()){
		str = sc.next();
		//将输入的字符串赋值给s[]数组,注意从s[1]开始赋值,因为s[0]为头结点,不存放数据
		for(int i = 0; i < str.length(); i ++){
			s[i+1] = str.charAt(i);
		}
		//s[]数组非0元素的长度为1+str.length()
		int n = str.length()+1;
		//第一次输入时,光标的当前位置与最后位置都在0处
		last = cur = 0;
		//next[0]相当于头结点的指针,在赋值之前指向null,此处的0就相当于null
		next[0] = 0;
		for(int i = 1; i <= n; 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])
			System.out.print(s[i]);
		
		}
	}
}

  对于以下代码段,理解起来可能较为困难,因此绘制图表来展示代码对输入的处理过程:

for(int i = 1; i <= n; 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])
			System.out.print(s[i]);
		
UVa11988:破损的键盘(悲剧文本)【Java】_第1张图片 当输入为“a[b]c”时的代码执行示意图

 

你可能感兴趣的:(算法刷题)