问题描述
试题编号: | 201709-3 |
试题名称: | JSON查询 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,可以用来描述半结构化的数据。JSON 格式中的基本单元是值 (value),出于简化的目的本题只涉及 2 种类型的值: 输入格式 第一行是两个正整数 n 和 m,分别表示 JSON 数据的行数和查询的个数。 输出格式 对于输入的每一个查询,按顺序输出查询结果,每个结果占一行。 样例输入 10 5 样例输出 STRING John 评测用例规模与约定 n ≤ 100,每行不超过 80 个字符。 |
解题思路对于这种很长很复杂的字符串处理模拟题很重要,好的解题思路可以大幅减小编程的难度。
本题的解题思路是,用一个map来储存所有的key和value,但是这个key要经过特殊处理。本题中的value可能嵌套有对象,一层一层用一个‘.’来连接,那么我们就把key处理成一个路径。意思就是对于每个value字符串,都把从第一层到这层的路径设为他的key。路径用就是每一层的key用‘.’连接起来。举个例子,对于本题给的样例输入,我们想得到的map是:
map[.firstName]=John;//第一层的key也加上 ‘.’ 是为了方便统一处理
map[.lastName]=Smith;
map[.address.streetAddress]=2ndStreet;
map[.address.city]=NewYork;
map[.address.state]=NY;
map[.esc\\aped]=\"hello\";
这样就可以实现,对于每个查询,都可以直接输出结果。但是有个问题就是如果当前层进入了嵌套,然后又退出了嵌套,继续输入当前层的key,我们怎么让路径也回退一个key?这里就要用到另一个map,用来将当前层的路径和嵌套层的路径对应起来。当遇到}时,说明退出了一层嵌套,这时候我们就可以通过嵌套层的路径把map中储存的当前层的路径找出来。因为一层中可能出现多个嵌套层,所以让当前层路径做value,嵌套层路径做key。代码如下,注释很详细:
#include<iostream>
#include<map>
using namespace std;
//one保存key和value,two保存当前层路径和嵌套层路径
map<string,string> one,two;
//处理字符串,去掉反斜杠,参数是i的引用,这样方便遍历
string deal(int &i,string a)
{
i++;
string res="";
while(1)
{
if(a[i]=='"')
break;
if(a[i]=='\\')
{
res+=a[i+1];
i++;
}
else
res+=a[i];
i++;
}
return res;
}
int main()
{
int n,m;
cin>>n>>m;
getchar();
//line用来连接输入的每一行,方便处理。name表示当前层的路径
string line="",temp,name="",key="",value="";
//将输入的每一行连接起来,方便处理
while(n--)
{
getline(cin,temp);
line+=temp;
}
int len=line.length();
for(int i=1;i<len-1;i++)
{
//跳过空格和逗号
if(line[i]==' ' || line[i]==',')
continue;
//遇到了},即一层嵌套的结束,这时候路径应该改成当前层的路径
else if(line[i]=='}')
name=two[name];
//遇到了",表示要输入key了,输入i的引用,在函数结束后,i便跳到了key的第二个引号上
else if(line[i]=='"')
key=deal(i,line);
//遇到了:,表示要输入value了
else if(line[i]==':')
{
i++;
//先去掉多余的空格
while(line[i]==' ')
i++;
//如果输入的是字符串,先处理,再存到map中
if(line[i]=='"')
{
value=deal(i,line);
//此时储存的是key的路径,用 . 连接
one[name+"."+key]=value;
}
//如果输入的value是嵌套的对象,就把key的value设为 OBJECT
else if(line[i]=='{')
{
//此时储存的是key的路径,用 . 连接
one[name+"."+key]="OBJECT";
//进入嵌套层前,先将嵌套层的路径和当前层的路径对应起来
two[name+"."+key]=name;
//路径改成嵌套层的路径
name=name+"."+key;
}
}
}
for(int i=0;i<m;i++)
{
getline(cin,temp);
//因为我们的map中的key的开头都有个 . ,所以查询时先加上
temp="."+temp;
if(one.find(temp)!=one.end())
{
if(one[temp]=="OBJECT")
cout<<"OBJECT"<<endl;
else
cout<<"STRING "<<one[temp]<<endl;
}
else
cout<<"NOTEXIST"<<endl;
}
return 0;
}