zoj 3826 Hierarchical Notation(模拟)

博客介绍了ZOJ 3826题目的解题思路,主要涉及模拟方法。通过建立树形结构并利用map数据结构来解析给定的语法,解决查找特定标签的问题。博主在比赛中初次尝试时遇到了一些混乱,但最终发现只需使用map就能简洁地解决问题。虽然现场比赛时因数组大小问题差点AC,但在后期编写代码时遇到了一些未在比赛中出现的异常数据,如value为{}的情况,这给博主带来了困扰。
摘要由CSDN通过智能技术生成

题意:就是根据给定的语法查找某个标签之类的东西。。。

思路:嘛,看起来建个树然后查就ok了,现场的时候开始写的有些乱,建了一堆结构体什么的,后来发现只需要用个map搞一搞就好了。map的一个节点代表一个value值,然后map里一个映射<string,int>代表key对应的value是什么,然后就根据结构建树就好了,现场如果不算我sb把数组开小了可以算1A了,但是回来写wa了好久,貌似有些现场没有的奇怪数据,比如value是{}之类的?感觉有些蛋疼


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#include<bitset>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-6
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn = 500000 + 10;
char str[maxn],s[maxn];
map<string,int>mp[maxn];
string Ends[maxn],S[maxn];
int tot,negcnt;
int solve(int L,int R)
{
    bool flag = true;
    for(int i = L;i <= R;++i)
        if(str[i] == ',' || str[i] == ':')
        {
            flag = false;
            break;
        }
    if(flag)
    {
        negcnt++;
        Ends[negcnt] = "";
        for(int i = L;i <= R;++i)
            Ends[negcnt] += str[i];
        return -negcnt;
    }
    int id = ++tot;
    if(str[L] == '{' && str[R] == '}') {L++;R--;}
    int last = L,cnt = 0;
    for(int i = L;i <= R;++i)
    {
        if(str[i] == '{') cnt++;
        if(str[i] == '}') cnt--;
        if(str[i] == ',' && cnt == 0)
        {
            string tmp = "";
            int j = last;
            while(str[j] != ':') tmp += str[j++];
            mp[id][tmp] = solve(j + 1,i - 1);
            last = i + 1;
        }
    }
    string tmp = "";
    int j = last;
    while(str[j] != ':') tmp += str[j++];
    mp[id][tmp] = solve(j + 1,R);
    return id;
}
void print(int rt)
{
    if(rt < 0)
    {
        cout<<Ends[-rt];
        return ;
    }
    cout<<"{";
    map<string,int>:: iterator it = mp[rt].begin();
    cout<<(it -> first)<<":";
    print(it -> second);
    it++;
    while(it != mp[rt].end())
    {
        cout<<","<<(it -> first)<<":";
        print(it -> second);
        it++;
    }
    cout<<"}";
}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        tot = negcnt = 0;
        int n = strlen(str);
        for(int i = 0;i <= n;++i) mp[i].clear();
        solve(0,n - 1);
//        print(1);
        int q;
        scanf("%d",&q);
        while(q--)
        {
            scanf("%s",s);
            n = strlen(s);
            int m = 0;
            string tmp = "";
            for(int i = 0;i < n;++i)
                if(s[i] == '.')
                {
                    S[m++] = tmp;
                    tmp = "";
                }
                else tmp += s[i];
            S[m++] = tmp;
            int now = 1;
            for(int i = 0;i < m;++i)
            {
                if(now < 0) {now = inf;break;}
                if(mp[now].find(S[i]) == mp[now].end())
                {
                    now = inf;
                    break;
                }
                else
                    now = mp[now][S[i]];
            }
            if(now == inf) cout<<"Error!"<<endl;
            else
            {
                print(now);
                puts("");
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值