POJ 2792 Brackets Removal

题意:给定一个表达式,去除所有能去掉的括号

分析:因为是表达式,所以想套用LR(1)分析法和分解表达式,一步一步手动模拟去括号,结果总是拆东墙补西墙,搞不出来。

三天后看解题报告,标程是通过加括号来解决的,构造一颗二叉树,去掉所有括号,叶子是变量,非叶子其他的节点是运算符,节点的深度和他所在的括号数相同,

由于*和/的计算优先级比加和减高,所以当非叶子节点的运算符的优先级比孩子节点的高时,必须通过加括号来维护

pascal的标程是错(虽然它的文件名已经含有bug的单词,但是错的怎么能放到标程里!),有两处错误,我都发现过,可都只改了一处来测试,耗了一个下午,

看到java版的编程才恍然大悟,不自信啊!

第一处:由于同深度同优先级的时候是从左往右计算的,而它却写成从右往左。

第二处:1,在当非叶子节点的运算符的优先级比孩子节点的高,要加括号时,取反运算符不(false)应该影响括号内,它是沿用父节点的inverse;

    2,而在同深度同优先级的时候,应该沿用父节点的inverse,它却是不影响(false);

#include<cstdio>
#define MAXN 1010
using namespace std;

struct ops
{
    int l,r,pr;
    char op;
};

ops o[MAXN];
char s[MAXN];
int k,p;
int expr();

int createOps(int l,int r,char op,int pr)
{
    k++;
    o[k].l=l;
    o[k].r=r;
    o[k].pr=pr;
    o[k].op=op;
    return k;
}

int factor()
{
    int ret;
    if(s[p]>='a'&&s[p]<='z')
        ret=createOps(0,0,s[p++],3);
    else
    {
        p++;
        ret=expr();
        p++;
    }
    return ret;
}

int term()
{
    int l,r,ret;
    char op;
    l=factor();
    while(s[p]=='*'||s[p]=='/')
    {
        op=s[p++];
        r=factor();
        l=createOps(l,r,op,2);
    }
    return l;
}

int expr()
{
    int l,r;
    char op;
    l=term();
    while(s[p]=='+'||s[p]=='-')//第一处,原为 if
    {
        op=s[p++];
        r=term(); //第一处,原为 r=expr();
        l=createOps(l,r,op,1);
    }
    return l;
}

void Print(int n,bool inverse)
{
    int l,r;
    if(o[n].op>='a'&&o[n].op<='z')
    {
        putchar(o[n].op);
        return;
    }
    l=o[n].l;
    r=o[n].r;
    if(o[l].pr>o[n].pr)
        Print(l,false);
    else if(o[l].pr<o[n].pr)
    {
        putchar('(');
        Print(l,false);//第二处的第一点 ,原为 Print(l,inverse);
        putchar(')');
    }
    else
        Print(l,inverse);//第二处的第二点  ,原为 Print(l,false);
        
    if(!inverse)
        putchar(o[n].op);
    else if(o[n].op=='+')
        putchar('-');
    else if(o[n].op=='-')
        putchar('+');
    else if(o[n].op=='*')
        putchar('/');
    else
        putchar('*');
    
    if(o[r].pr>o[n].pr)
        Print(r,false);
    else if(o[r].pr<o[n].pr)
    {
        putchar('(');
        Print(r,false);
        putchar(')');
    }
    else//如果不改第一处的话,错误就会在这里产生 
    {
        if(o[n].op=='-'||o[n].op=='/')
            inverse=!inverse;
        Print(r,inverse);
    }
}

int main()
{
    gets(s);
    k=p=0;
    int n=expr();
    Print(n,false);
    return 0;    
}
原文地址:https://www.cnblogs.com/xchaos/p/2532163.html