一般来说,把一颗子树离散成一个int,把一个结点的字符离散成一个int会方便处理
直接map离散。当然一个结点最多只有4个小写字母,也可以直接编码成一个27进制的整数,舍掉0,为了区分0和0000。
需要注意的是有可能只有一个结点。
#include<bits/stdc++.h> using namespace std; const int maxlen = 5e5; const int maxn = 5e4+1; char str[maxlen]; map<string,int> smp; map<string,int>::iterator sit; vector<string> scache; #define PB push_back struct Node { int l,r; int sid; int Hash; bool operator < (const Node& x) const{ return sid<x.sid || (sid==x.sid && (l < x.l || (l == x.l && r < x.r) )); } }tr[maxn]; map<Node,int> mp; map<Node,int>::iterator it; #define se second #define fi first #define MP make_pair int id_cnt; int SID(string &s) { if((sit = smp.find(s)) != smp.end()) return sit->se; scache.PB(s); smp.insert(MP(s,scache.size())); return scache.size(); } int ID(Node &nd) { if((it = mp.find(nd)) != mp.end()) return it->se; mp.insert(MP(nd,id_cnt)); tr[id_cnt] = nd; return id_cnt++; } int build(int x,int &len) { Node u; u.Hash = 0; string s; int i; for(i = x; str[i]; i++){ if(str[i] == ',' || str[i] == ')'){ s.assign(str+x,str+i); u.sid = SID(s); len = s.size(); u.l = u.r = -1; return ID(u); }else if(str[i] == '('){ s.assign(str+x,str+i); u.sid = SID(s); int lsz, rsz; u.l = build(++i,lsz); i += lsz; u.r = build(++i,rsz); len = s.size()+lsz+rsz+3; return ID(u); } } s.assign(str+x,str+i);//只有一个结点 u.sid = SID(s); u.l = u.r = -1; return ID(u); } int dfs_clock; void dfs(int u) { if(!tr[u].Hash){ tr[u].Hash = ++dfs_clock; printf("%s",scache[tr[u].sid-1].c_str()); }else { printf("%d",tr[u].Hash); return; } if(~tr[u].l){ putchar('('); dfs(tr[u].l); putchar(','); dfs(tr[u].r); putchar(')'); } } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d ",&T); while(T--){ gets(str); mp.clear(); id_cnt = 0; scache.clear(); smp.clear(); int len; int root = build(0,len); dfs_clock = 0; dfs(root);putchar(' '); } return 0; }