題目連接:編程
題目簡介:ide
(1)題目中的集合由 A-Z 的大寫字母組成,例如 "{ABC}" 的字符串表示 A,B,C 組成的集合。ui
(2)用運算符三種集合運算,'+' 表示兩個集合的並集,'*' 表示兩個集合的交集, '-' 表示從第一個集合中排除第二個集合包含的元素。編碼
(3)給出這樣的表達式,求出表達式結果(按照字母順序)。運算符優先級和編程語言中的規定相同,即優先級從高到低爲括號,乘號,加/減號;相同優先級時從左向右。spa
例如: "{ABC}+{BCD}" = "{ABCD}";code
題目分析:blog
屬於常規的表達式求值,方法是藉助兩個棧來解析。本質上來說,這是一個簡單題目,可是細節比較繁瑣,要寫對須要耐心。集合能夠用 bitset 來表示這個集合,因爲集合的元素數目不會超過 26,所以用 uint32 整數便可表示集合,這樣能夠把集合運算轉換爲整數的位操做來完成,比直接處理字符串更加方便。例如:字符串
s1: { A } -> n1 = 0x01;get
s2: { B } -> n2 = 0x02;
則:(s1+s2)轉換爲(n1 | n2)。
題目聲明輸入數據都是合法的表達式,不須要考慮表達式合法性判斷。則只須要表達式的解析,解析過程由運算符驅動,其中須要注意的細節有:
(1)左括號在棧內和棧外的優先級須要區分對待(在棧外具備最高優先級,入棧後則優先級下降,以讓後續的運算符可以入棧)。
(2)右括號實際上不入棧,而是做爲一個信號,負責把和它匹配的左括號從棧中彈出。
(3)在解析前,提早在運算符棧中壓入一個左括號,這樣編碼形式就會統一(不須要考慮在最開始階段,取不到棧內的運算符優先級的問題)。
(4)解析結束後,取出操做數棧中的惟一元素便可。再將其解析爲字符串形式。
須要考慮的特殊狀況好比:
({A})+({B}) 至關於:(1)+(2);
提交代碼:
#include <stdio.h> #include <string.h> char stack_op[256]; unsigned int stack_num[256]; int top_op; int top_num; int GetPrecedence(char op, int bInStack); char* GetNumber(char *str, unsigned int *pNum); unsigned int Compute(char* line); int main(int argc, char* argv[]); int GetPrecedence(char op, int bInStack) { switch(op) { case 0: return 1; case '(': return bInStack? 1 : 100; case ')': return 1; case '+': return 2; case '-': return 2; case '*': return 3; } return 0; } /* {ABCDEFG}+ | | str ret_val */ char* GetNumber(char *str, unsigned int *pNum) { char *pCh = str + 1; *pNum = 0; while(*pCh != '}') { if(*pCh >= 'A' && *pCh <= 'Z') *pNum = *pNum | (1 << (*pCh - 'A')); ++pCh; } return pCh; } unsigned int Compute(char* line) { char *pCh; unsigned int n1, n2, result; int prec1, prec2; top_op = 0; stack_op[top_op] = '('; top_num = -1; pCh = line; while(1) { if(*pCh == '{') { pCh = GetNumber(pCh, &n1); ++top_num; stack_num[top_num] = n1; } else { prec2 = GetPrecedence(*pCh, 0); prec1 = GetPrecedence(stack_op[top_op], 1); if(prec2 > prec1) { ++top_op; stack_op[top_op] = *pCh; } else { while(prec2 <= prec1 && strchr("*+-", stack_op[top_op]) != NULL) { n1 = stack_num[top_num - 1]; n2 = stack_num[top_num]; switch(stack_op[top_op]) { case '+': result = (n1 | n2); break; case '-': result = (n1 & (~n2)); break; case '*': result = (n1 & n2); break; } --top_num; stack_num[top_num] = result; --top_op; prec1 = GetPrecedence(stack_op[top_op], 1); } if(*pCh == ')') { while(stack_op[top_op] != '(') { --top_op; } --top_op; } else if(*pCh == 0) break; else { /* push current operator into stack */ ++top_op; stack_op[top_op] = *pCh; } } } ++pCh; } /* __ENDOF__ while(1) */ if(top_num == 0) result = stack_num[0]; else result = 0; return result; } int main(int argc, char* argv[]) { unsigned int result, x; char line[256]; while(gets(line) != NULL) { result = Compute(line); printf("{"); for(x = 0; x < 26; x++) { if(result & (1 << x)) printf("%c", x + 'A'); } printf("}\n"); } return 0; }
提交結果:
Judge Status | Problem ID | Language | Run Time(ms) | Run Memory(KB) |
Accepted | 1958 | C | 0 | 172 |