分析:直接模拟即可,这里用队列记录访问过的点,栈记录父节点。另外要注意的是在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;
}HDU ACM 4041 Eliminate Witches! 队列和栈模拟DFS
原文地址:http://blog.csdn.net/a809146548/article/details/45691455