您的位置:首页 > 其它

uva12219 Common Subexpression Elimination

2016-11-03 15:33 218 查看
Let the set  consist of all words composed of 1-4 lower case letters,

such as the words \ a “, \ b “, \ f “, \ aa “, \ fun ” and \ kvqf “.

Consider expressions according to the grammar with the two rules E ! f

E ! f ( E;E ) for every symbol f 2 . Any expression can easily be

represented as a tree according to its syntax. For example, the

expression \ a(b(f(a,a),b(f(a,a),f)),f(b(f(a,a),b(f(a,a),f)),f)) ” is

represented by the tree on the left in the following gure: Last night

you dreamt of a great invention which considerably reduces the size of

the representation: use a graph instead of a tree, to share common

subexpressions. For example, the expression above can be represented

by the graph on the right in the gure. While the tree contains 21

nodes, the graph just contains 7 nodes. Since the tree on the left in

the gure is also a graph, the representation using graphs is not

necessarily unique. Given an expression, nd a graph representing the

expression with as few nodes as possible! Input The rst line of the

input contains the number c (1  c  200), the number of expressions.

Each of the following c lines contains an expression according to the

given syntax, without any whitespace. Its tree representation contains

at most 50 000 nodes. Output For each expression, print a single line

containing a graph representation with as few nodes as possible. The

graph representation is written down as a string by replacing the

appropriate subexpressions with numbers. Each number points to the

root node of the subexpression which should be inserted at that

position. Nodes are numbered sequentially, starting with 1; this

numbering includes just the nodes of the graph (not those which have

been replaced by numbers). Numbers must point to nodes written down

before (no forward pointers). For our example, we obtain `

a(b(f(a,4),b(3,f)),f(2,6)) ‘

通过dfs进行建树和去重,关键是判断两棵树是否完全相同。可以对子树进行编号,每个三元组{自身的字符串(的哈希值),左子树编号,右子树编号}对应唯一的编号,在map里进行查询。

注意时限卡的比较紧,建树要做到O(n)。

#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
#include<algorithm>
#include<map>
#include<iostream>
using namespace std;
#define LL unsigned long long
const int pp=131;
struct st
{
char s[5];
int u,v,l;
LL h;
bool operator < (const st ss) const
{
int i;
if (h!=ss.h) return h<ss.h;
if (u!=ss.u) return u<ss.u;
return v<ss.v;
}
}a[1000000];
map<st,int> mp;
char s[500000];
int len[1000000],num[1000000],ord[1000000],last[1000000],tot,l,r,cnt,clo,now,K;
bool b[1000000];
int build()
{
int i,j,k,cnt,q;
bool flag=0;
st tem;
tem.l=tem.h=0;
while (now<=l&&(s[now]!=','&&s[now]!='('&&s[now]!=')'))
{
tem.s[++tem.l]=s[now];
tem.h=tem.h*pp+s[now];
now++;
}
tem.s[tem.l+1]=0;
if (s[now]=='(')
{
now++;
tem.u=build();
now++;
tem.v=build();
now++;
}
else tem.u=tem.v=0;
if (!mp.count(tem))
{
a[++tot]=tem;
mp[tem]=tot;
}
return mp[tem];
}
void prt(int p)
{
if (last[p]<K)
{
last[p]=K;
ord[p]=++clo;
printf("%s",a[p].s+1);
if (!a[p].u) return;
printf("(");
prt(a[p].u);
printf(",");
prt(a[p].v);
printf(")");
}
else printf("%d",ord[p]);
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
K++;
scanf("%s",s+1);
l=strlen(s+1);
tot=0;
now=1;
clo=0;
cnt=0;
mp.clear();
prt(build());
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs 哈希