UVA - 12219(唯一性标记法的应用)

来源:互联网 发布:java用for循环打印菱形 编辑:程序博客网 时间:2024/05/22 03:47

用唯一性标记法,在递归建树时,给每个数分配唯一识别编号记为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;}


0 0
原创粉丝点击