zoukankan      html  css  js  c++  java
  • UVA

    /*
      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("
    ");
    		
    	}
    	return 0;
     } 

  • 相关阅读:
    【Codeforces 349B】Color the Fence
    【Codeforces 459D】Pashmak and Parmida's problem
    【Codeforces 467C】George and Job
    【Codeforces 161D】Distance in Tree
    【Codeforces 522A】Reposts
    【Codeforces 225C】Barcode
    【Codeforces 446A】DZY Loves Sequences
    【Codeforces 429B】Working out
    【Codeforces 478C】Table Decorations
    【Codeforces 478C】Table Decorations
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789407.html
Copyright © 2011-2022 走看看