表达式求值 ZOJ_3585_2

本文介绍了一种基于递归下降解析器的方法来解析和评估布尔表达式,通过定义文法并实现相应的函数,能够在O(n)的时间复杂度内完成表达式的计算。文章提供了完整的C语言实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参照龙书《编译原理》的前三章的方式写的代码,先写出文法:

{}为可选内容, || 为或者选项。

exp = term {^ term}  // 异或

term = fact {| fact} // 或

fact = var {& var} // 与

var = 变量 || ! 变量  || (exp) 


根据文法规则写出各个函数,设置好全局字符串指针指向的表达式,然后a = exp() 就能得到改表达式的结果。

表达式计算的时间的复杂度为O(n)。

因为最多15个变量,枚举各个变量的值的次数不超过2^15,算法总复杂度为O(l*2^n),2s内得解。

#include<stdio.h>
#include<string.h>
#include<ctype.h>
char s1[205], s2[205] ;
char e1[205], e2[205] ;
int len1, len2 ,le1, le2 ,nVar , V;
char name[20][50] ;
char *s;
int p ;

int find(char *p){
	for(int i=0;i<nVar;i++){
		if(strcmp( p, name[i]) == 0)	return i ;	
	}
	return -1 ;	
}
int add(char *p){
	strcpy(name[nVar] , p) ;		
	nVar ++ ;
	return nVar - 1;
}
bool isOP(char c){
	if(c=='!' || c=='&' || c=='|' || c=='^' || c=='(' || c==')' )	return true ;
	else return false ;	
}

bool exp() ;
bool term() ;
bool fact() ;
bool var() ;
/*
根据运算符的优先级来逐步完成 
*/
bool exp(){
	bool a ,b;
	a = term() ;
	while(s[p] == '^'){
		p++ ;
		b = term() ;
		a = a ^ b ;	
	}		
	return a ;
}
bool term(){
	bool a ,b ;
	a = fact() ;
	while(s[p] == '|'){
		p++ ;
		b = fact() ;
		a = a | b ;	
	}	
	return a ;
}
bool fact(){
	bool a , b ;
	a = var(); 
	while(s[p] == '&'){
		p++ ;
		b = var() ;
		a = a & b ;	
	}	
	return a ;
}
bool var(){
	bool a ;
	if(s[p]<nVar){
		a = (V&(1<<s[p])) > 0 ;
		p++ ;
		return a ;
	}	
	else if(s[p] == '!'){
		p++ ;
		a = var() ;
		a = !a ;
		return a ;
	}
	else if(s[p] == '('){
		p++ ;
		a = exp() ;
		p++ ;
		return a ;		
	}
}

int main(){
	int i, j ;
	char str[50] ;
	while(gets(s1) && s1[0]){
		gets(s2) ;
		i = 0 ; le1 = 0 ; le2 = 0 ; nVar = 0 ;
		while( s1[i] ){
			if(isalpha( s1[i] )){
				j = 0 ;
				while( s1[i] && isalpha(s1[i]))
					str[j++] = s1[i++] ;	
				str[j] = 0 ;
				int id = find(str);
				if(id == -1)	id = add(str);
				e1[le1++] = id ;
			}	
			else if(isOP( s1[i] )){
				e1[le1++] = s1[i] ;	
				i++ ; 
			}
			else 
				i++ ;
		}
		e1[le1] = 0 ;
		i = 0 ;
		while( s2[i] ){
			if(isalpha( s2[i] )){
				j = 0 ;
				while( s2[i] && isalpha(s2[i]))
					str[j++] = s2[i++] ;	
				str[j] = 0 ;
				int id = find(str);
				if(id == -1)	id = add(str);
				e2[le2++] = id ;
			}	
			else if(isOP( s2[i] )){
				e2[le2++] = s2[i] ;	
				i++ ; 
			}
			else 
				i++ ;
		}
		e2[le2] = 0 ;
		bool ok = 1 ;
		for( V=(1<<nVar)-1 ;V>=0; V--){
			s = e1 ;
			p = 0 ;
			bool exp1 =  exp();
			s = e2 ;
			p = 0 ;
			bool exp2 = exp() ;
			if(exp1 != exp2){
				ok = 0 ; break ;		
			}
		}
		if(ok)	printf("TRUE\n");
		else 	printf("FALSE\n");
	}	
	
	return  0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值