问题描述
在显示屏上盲打一段文字,在这过程中由于键盘的问题,Home键与end键会自动按下,显有一段文本,其中‘[’表示Home键按下,‘]’表示End键按下,求出显示屏上的文字排序
示例输入
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University
示例输出
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University
问题分析
废话:
很容易有这样的思路,找出‘[’与‘]’之间的文字将其移到文字的最前面即可,但是对于在一段文字前插入字符,每插入一个字符,在下一次插入时,其耗费的时间便越长,需要剩余文本全体想后移一位。故而,单纯的使用数组是不可取的。
借助于链表的思想,设定一个next,使得每个元素与下一个元素有一定的关联,传统意义上的链表多用指针来表示,但是在算法竞赛中,使用指针实在不是上上之选,而且也过于麻烦,因此我们这样假定:
s[ ]:输入的样本为字符数组,s[0]设为0,字符从s[1]开始输入
next[ ]:s[next[i]]=p[i+1](p[ ]:输出的样本为字符数组) 即next[i]表示s[i]的下一个
#include
#include
#include
#define maxn 1000
int main()
{
int last,cur,next[maxn]; //last记录末位置,cur指向当前位置,next[]记录输出顺序
int i;
char s[maxn]; //输入字符串
while(scanf("%s",s+1)==1) //s[0]空出
{
last=cur=0;
next[0]=0; //next[i]置0,意为不指向任何值
for(i=1;i<=strlen(s+1);i++)
{
if(s[i]=='[') cur=0; //当输入]时,cur光标指向首位置
else if(s[i]==']') cur=last; //当输入]时,cur光标指向末尾
else //当读入其他字符时,插值操作
{
next[i]=next[cur];
next[cur]=i;
if(last==cur) last=i; //当末尾值和当前光标位置相同时,last和cur一样向i跟进
cur=i; //尾光标向后移动
}
}
//顺次输出
for(i=next[0];i!=0;i=next[i])
printf("%c",s[i]);
printf("\n");
}
return 0;
}
刘汝佳一上来就把链表的核心抛出来了,我足足看了一下午。
0.为了方便起见,常常在链表第一个元素之前放一个虚拟节点s[0]
1.光标cur,最后一个字符编号last,其实只是由于这题home,end的条件限制,如果用数组建立单链表,只需要next[i]和s[i]
2.其中next[i]是s[i]连的下一个字符的编号,比如:
s[0],next[0]=3连下一个字符->
s[next[0]],next[next[0]]
3.在本题中,如果next[i]=0,说明不知道这个节点连哪个下一个节点,如果全部插入完节点,遇到next[i]=0,就意味着这个链表已经结束
所以有如下对链表遍历的方法:
for(i=next[0];i!=0;i=next[i])
printf("%c",s[i]);
4.下面说说如何插入
s[i]对应一个next[i],那么s[i]下一个连的是s[next[i]],next[next[i]]
如果在s[i]后面插入s[j]next[j]
只需next[j]=next[i],next[i]=j
新节点j先插到s[i]指向的s[next[i]]的前面,再把前面i的后面连的那个节点改为新插入的那个j
5.再来说说本题
a.只需改变s的输出顺序,输出s[next[i]]
b.多了个[],就是说插入的位置会发生变化。
★c.next[]数组来记录输出顺序。★
加下来使用一组输入演示过程,便于理解,需要提醒的是:下图中s是输入字符串,当输出next的下标对应的s中的字符时,下一个要输出的字符的下标的next下标,是当前next的值
(纠正,下图中是next下标,不是下表)
比如一般输入abc[def]xyz
输入a的时候next[0]=0,输入b的时候next[0]=1,next[1]=0 ,输入c的时候next[2]=next[1]=0,next[1]=i=2,以此类推
当i=4时,读到‘[’的时候,cur置0,光标指到首位,
进入下一个循环,将首位的next值提到next[i]的位置:
变成next[0]=5,next[5]=1,此时last停留在last=4;
接着继续else if循环,知道读到‘]’,此时进入if语句cur=last=4,
继续循环,将会进入else if语句将next[cur]赋值给next[i],将i赋值给next[i],如下:
继续循环直到结束,会得到以下结果:
接下来按照next[]的指示
for(i=next[0];i!=0;i=next[i])
printf("%c",s[i]);
next[0]=5 即输出s[5];next[next[0]=5]=6 即输出s[6];next[next[6]=7] 即输出s[7];next[next[6]=7]=1,即输出s[1];以此类推
输出:
defabcxyz
6.悟道可能时算法学习必经之路,多看就明白了