分析:直接模拟即可,这里用队列记录访问过的点,栈记录父节点。另外要注意的是在strlen(str)计算字符串的时候要预先计算出来保存在变量中,for直接用,如果for循环直接调用strlen,那么每次都会重新计算,该題字符串的数据量很大,就会存在大量的无用计算,还导致了一次TLE,唉!以前没注意到这里。
#include<iostream> #include<vector> #include<queue> #include<stack> using namespace std; char room[50005][12]; queue<int> q; stack<int> s; char str[1000005]; int main() { int T,i,sum,j,len; scanf("%d",&T); while(T--) { scanf("%s",str); sum=0; j=0; len=strlen(str); //事先计算,避免每次计算,数据大时就会影响到效率 for(i=0;i<len;i++) //队列q用于保存路径上经过的节点,插入时均插入当前非字母字符前面的节点 { if(str[i]>='a' && str[i]<='z') //栈用于保存进入的路径 room[sum][j++]=str[i]; else { if(j!=0) //处理两个连续的非字母情况。 { room[sum++][j++]='\0'; j=0; } if(str[i]=='(') //进入节点 { s.push(sum); q.push(sum); } else if(str[i]==',') { if(str[i-1]!=')') //退回父节点 { q.push(sum); q.push(s.top()); } else //退到该节点的父节点的父节点 { q.push(s.top()); s.pop(); q.push(s.top()); } } else if(str[i]==')') { if(str[i-1]!=')') //记录前一个节点 q.push(sum); else //出栈 { q.push(s.top()); s.pop(); } if(s.size()==1) //回到根节点 { q.push(s.top()); //插入根节点 s.pop(); //之后栈为空 } } } } if(sum==0) printf("1\n%s\n",str); else { printf("%d\n",sum); for(i=0;i<sum;i++) printf("%s\n",room[i]); while(q.size()!=1) { printf("%d ",q.front()); q.pop(); printf("%d\n",q.front()); } q.pop(); //退出根节点 } printf("\n"); } return 0; }
时间: 2024-10-01 04:13:18