UVA

来源:互联网 发布:vb 数组赋值 编辑:程序博客网 时间:2024/06/08 15:05
/*  1. Home键的作用是将光标定位到文首,End键的作用是将光标定位到文尾    2. 在数组中频繁移动(尤其插入和删除)元素比较低效,如果可能尽量使用链表    3. 虽然一般讲链表会讲到指针,但链表实现方式,并非一定需要指针,例如此题*//*  ------------------心路历程分割线,可以直接跳过------------------  还是第一次接触这种,不用指针来表示链表的表示方法,一开始想了很久很久,甚至用了许多笨方法    比如自己举出几个例子,对于每个位置,分别列出i 对应的 next[i] cur last 的数据变化情况...    但后来用excel举出一个例子,一个个填充对应数据时,却发现自己越写越乱,每次到最后,总是觉得前面好像哪里弄错了,但是一步一步后推回去找错,又比从头开始麻烦,于是又清空excel,一个个列出对应情况的3个数据,并找出它们的规律和变化关系    这么死板地套了很久,套不出来就先去吃饭,路上走着走着,突然想到了 cur 和 last的实际意义,以及next[i]本身,和next[i]的每次更新,其实都是有规律可循的,于是赶紧吃个饭打开电脑记下来思路,免得待会又不明白了 T^T  ------------------心路历程分割线,可以直接跳过------------------    注意:!!!  对我的代码而言,数组下标从1开始,因为输入时就是以s[1]作为起点的,毕竟是 scanf("%s", s + 1); 这样做的目的是---前面的s[0]可以单独保留,作为“头节点”,这样在将[]里的信息运用“头插法”插入时,表示就会比较方便了  cur的含义:当前的序号,也就是循环到下一个位置时,下一个位置的前驱,在数组s中的下标(看上去有点绕,但不用指针的话,必然得牺牲一点通俗性的,多看几次还是能明白的),例如对 abc[test]def,当循环到 a时,i为1  cur = i = 1, cur既是当前走到的位置,又是走到的下一个位置,也就是b时,b的前驱字母a,在s中的下标    last:  注意在没遇到[ 或者是 ]之前,last 是和 cur同步移动的,但是遇到 [以后,last就一直停留在 [ 的前一个位置的对应下标。举个例子  ...A[...]B...  假设A和B之间的,是这个串中遇到的第一个中括号对,在A之前,last和cur一直同步移动,且都是当时的i,遇到[之后,last就一直停留在A的位置的下标了  可是保留A的下标又有什么用呢?  当然有用啦!在遇到]以后,我们要更新]的下一个位置的前驱的下标(也就是B的下标,也就是循环到]时,当时的cur),所以遇到]时,所做的处理就是cur变为last了,毕竟B当然是接到A后面的,因为两个中括号只是代表 Home和End键被无意按下,并不出现在真实的文本中,而[]中括号对里面的内容,都被头插到头节点的后面了    其实从这里也就可以理解,为什么遇到[时,将cur赋值0了,因为[后面的文本就是要移动到文本最前端的,当时的cur代表[的下一个元素的前驱(头结点)在s数组中的下表(0),自然就是 cur = 0的处理了    至于既不是[也不是]的普通内容,那就是每次遇到一个新位置,将其前一个位置的后继next[i]接到自己的后继上(next[i] = next[cur]),再将自己作为前一个位置的后继(next[cur] = i),再为其下一个位置预备好位置前驱,(即移动光标,使cur = i,含义是,循环走到下一个位置时,其前驱位置就是当前位置i了<当然,除非被中括号破坏了>),以及last是为了停在[的前一个位置,所以在此之前,除了出现[和]的情况以外,last总是和cur同步移动,总是同一个值    总结:  一道比较值得回味的题,如果深入想想,多举几个例子,比如多对括号以]结束整个串,多对中括号,以普通字母结束整个串,等等    以及,这个不用指针来表示链表的方式,真的很神奇啊!而且也很值得琢磨研究,越想越觉得有意思,越想越觉得自己好像有些小细节还有些懵懵懂懂,真的很值得重看!!*/



#include <cstdio>#include <cstring>const int maxn = 1e5 + 5;int last, cur, next[maxn]; //next[i]存放:i后面接着的数,在s中的下标//cur表示光标位置,当前光标位于 s[cur]的右边//last表示显示屏的最后一个字符是s[last] char s[maxn];int main(){while (scanf("%s", s + 1) == 1){memset(next, 0, sizeof(next));int n = strlen(s + 1); //输入保存在s[1], s[2], s[3]......last =  cur = 0;next[0] = 0;for (int i = 1; i <= n; i++){char ch = s[i];switch(ch){case '[': cur = 0; break;case ']': cur = last; break;default:next[i] = next[cur]; //将前一个字符的后缀序号,置为当前字符的后缀序号next[cur] = i; //前一个字符的后缀,变为当前元素的序号if (cur == last) last = i; //更新“最后一个字符”的标号cur = i; //移动光标 break;}}for (int i = next[0]; i != 0; i = next[i])printf("%c", s[i]);printf("\n");}return 0; }