用唯一性标记法,在递归建树时,给每个数分配唯一识别编号记为id ,用map来记录(name,lson_id, rson_id)是否被标记过。
方法,很简单,但是有一点就是建树的时候遍历字符串,一定要做到o(n) ,否则超时。
下面为自己的,版本,简言之,先建树,唯一标记每棵子树,(因为序号分配是从下往上不同于题目要求,有重新转化为题目要求的编号)
#include <set> #include <map> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; const int maxn = 1005555; struct node{ string c; int l,r; node(string c="0",int l=0,int r=0): c(c),l(l),r(r){} bool operator <(const node& rhs)const{ if(c!=rhs.c){ return c < rhs.c; } else{ return l<rhs.l||(l==rhs.l&&r<rhs.r); } } }; map<node,int> vis; vector<node> idcache; int ID(node c){ if(vis.count(c)) return vis[c]; idcache.push_back(c); return vis[c]=idcache.size(); } typedef struct tree* pointer; struct tree{ int id; string s; pointer Left,Right; tree(string s="0",pointer x=NULL,pointer y=NULL): s(s),Left(x),Right(y){} }; pointer root; char str[maxn],src[maxn],*p; int build(pointer& u){ u = new tree(); int i,cnt=0; u->s.clear(); while(islower(*p)){ u->s.push_back(*p); p++; } if(*p!='('){ return u->id=ID(node(u->s,0,0)); } p++; int num1 = build(u->Left); p++; int num2 = build(u->Right); p++; return u->id=ID(node(u->s,num1,num2) ); } void dfs(pointer u){ if(u->Left==NULL){ if(vis.count(node(u->s,0,0))) printf("%d",vis[node(u->s,0,0)]); else { ID(node(u->s,0,0)); cout<<u->s; } return ; } if(vis.count(node(u->s,u->Left->id,u->Right->id))) printf("%d",vis[node(u->s,u->Left->id,u->Right->id)]); else{ cout<<u->s; ID(node(u->s,u->Left->id,u->Right->id)); printf("("); dfs(u->Left); printf(","); dfs(u->Right); printf(")"); } } int main() { int T; scanf("%d",&T); while(T--){ scanf("%s",str); vis.clear(); idcache.clear(); p= str; build(root); vis.clear(); idcache.clear(); dfs(root); printf("\n"); } return 0; }
但是,可以用数组式建树预分配编号。若已经被访问取消预分配。
#include <set> #include <map> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; const int maxn = 100000; char str[maxn*5],src[maxn],*p; struct node{ string s; int left,right,ha; bool operator < (const node& rhs)const{ if(ha!=rhs.ha) return ha<rhs.ha; else if(left!=rhs.left) return left<rhs.left; else return right<rhs.right; } }a[maxn]; int cn=0,fu=1; map<node,int> vis; int build(){ int id = cn++; node& u=a[id]; u.s.clear(); u.ha = 0; u.left=u.right = -1; while(islower(*p)){ char c = *p; u.s.push_back(c); u.ha=u.ha*27+(c)-'a'+1; p++; } if(*p=='('){ p++; u.left=build(); p++; u.right=build(); p++; } if(vis.count(u)){ cn--; return vis[u]; } return vis[u] = id; } int T,V[maxn*6]; void dfs(int id){ if(V[id] == T) printf("%d",id+1); else { V[id] = T; printf("%s",a[id].s.c_str()); if(a[id].left!=-1){ printf("("); dfs(a[id].left); printf(","); dfs(a[id].right); printf(")"); } } } int main() { int ca; scanf("%d",&ca); for(T=1;T<=ca;T++){ scanf("%s",str); cn=0; vis.clear(); p = str; build(); dfs(0); printf("\n"); } return 0; }