CSP-J 2022_第三題邏輯表達式

題目

邏輯表達式是計算機科學中的重要概念和工具,包含邏輯值、邏輯運算、邏輯運算優先級等內容。
在一個邏輯表達式中,元素的值只有兩種可能:0(表示假)和 1(表示真)。元素之間有多種可能的邏輯運算,本題中只需考慮如下兩種:“與”(符號為 &)和“或”(符號為 |)。其運算規則如下:
0&0=0&1=1&0=0,1&1=1;
0∣0=0,0∣1=1∣0=1∣1=1。
在一個邏輯表達式中還可能有括號。規定在運算時,括號內的部分先運算;兩種運算并列時,& 運算優先于 | 運算;同種運算并列時,從左向右運算。
比如,表達式 0|1&0 的運算順序等同于 0|(1&0);表達式 0&1&0|1 的運算順序等同于 ((0&1)&0)|1。
此外,在 C++ 等語言的有些編譯器中,對邏輯表達式的計算會采用一種“短路”的策略:在形如 a&b 的邏輯表達式中,會先計算 a 部分的值,如果 a=0,那么整個邏輯表達式的值就一定為 0,故無需再計算 b 部分的值;同理,在形如 a|b 的邏輯表達式中,會先計算 a 部分的值,如果 a=1,那么整個邏輯表達式的值就一定為 1,無需再計算 b 部分的值。
現在給你一個邏輯表達式,你需要計算出它的值,并且統計出在計算過程中,兩種類型的“短路”各出現了多少次。需要注意的是,如果某處“短路”包含在更外層被“短路”的部分內則不被統計,如表達式 1|(0&1) 中,盡管 0&1 是一處“短路”,但由于外層的 1|(0&1) 本身就是一處“短路”,無需再計算 0&1 部分的值,因此不應當把這里的 0&1 計入一處“短路”。

輸入格式
輸入共一行,一個非空字符串 s 表示待計算的邏輯表達式。

輸出格式
輸出共兩行,第一行輸出一個字符 0 或 1,表示這個邏輯表達式的值;第二行輸出兩個非負整數,分別表示計算上述邏輯表達式的過程中,形如 a&b 和 a|b 的“短路”各出現了多少次。

輸入輸出樣例
輸入 #1
0&(1|0)|(1|1|1&0)
輸出 #1
1
1 2
輸入 #2
(0|1&0|1|1|(1|1))&(0&1&(1|0)|0|1|0)&0
輸出 #2
0
2 3
說明/提示
【樣例解釋 #1】
該邏輯表達式的計算過程如下,每一行的注釋表示上一行計算的過程:

0&(1|0)|(1|1|1&0)
=(0&(1|0))|((1|1)|(1&0)) //用括號標明計算順序
=0|((1|1)|(1&0)) //先計算最左側的 &,是一次形如 a&b 的“短路”
=0|(1|(1&0)) //再計算中間的 |,是一次形如 a|b 的“短路”
=0|1 //再計算中間的 |,是一次形如 a|b 的“短路”
=1
【數據范圍】

設 ∣s∣ 為字符串 s 的長度。

對于所有數據,1≤∣s∣≤10
6
。保證 s 中僅含有字符 0、1、&、|、(、) 且是一個符合規范的邏輯表達式。保證輸入字符串的開頭、中間和結尾均無額外的空格。保證 s 中沒有重復的括號嵌套(即沒有形如 ((a)) 形式的子串,其中 a 是符合規范的邏輯表達式)。
在這里插入圖片描述
其中:
特殊性質 1 為:保證 s 中沒有字符 &。
特殊性質 2 為:保證 s 中沒有字符 |。
特殊性質 3 為:保證 s 中沒有字符 ( 和 )。

【提示】

以下給出一個“符合規范的邏輯表達式”的形式化定義:

字符串 0 和 1 是符合規范的;
如果字符串 s 是符合規范的,且 s 不是形如 (t) 的字符串(其中 t 是符合規范的),那么字符串 (s) 也是符合規范的;
如果字符串 a 和 b 均是符合規范的,那么字符串 a&b、a|b 均是符合規范的;
所有符合規范的邏輯表達式均可由以上方法生成。

代碼

#include <bits/stdc++.h>//萬能頭文件,包含c++標準庫中常用頭文件 
using namespace std;//使用std命名空間,使用標準庫中類型、函數時無需std::前綴 
int n_yu,n_huo; //與和或運算短路次數 
struct node{//二叉樹節點類型 char x;//操作符號'&'、'|'、'('、')' 、'0'、'1' bool k;//各邏輯運算結果 node *fa, *left, *right;//指向父、左、右節點的指針 node() : x('*'),fa(nullptr), left(nullptr), right(nullptr) {}//默認構造函數,初始化節點 node(char cx){//帶參構造函數,根據字符初始化節點 x=cx,fa=nullptr, left=nullptr, right=nullptr;if(cx=='1'||cx=='0')k=cx-'0';}
};
class Tree{public:node *root,*current;    // 根節點指針,當前操作節點指針(構建樹時用)// 構造函數:初始化根節點和當前節點Tree(){//構造函數,構造根節點為'r'(不變),當前節點指向根 root=new node('r'), current=root;}~Tree() {// 析構函數:遞歸釋放整個語法樹節點內存clear(root);root = current = nullptr;}void insert(char x) {//根據字符類型,插入并構建語法樹     node* newNode = new node(x);// 創建新節點if(x=='0'||x=='1'||x=='('){//操作數和左括號 newNode->fa = current;//成為當前節點的子節點 if(!current->left)current->left = newNode;//當前節點左子節點空,就掛到左節點 else if(!current->right)current->right = newNode;//否則掛右節點 }else if(x==')'){//右括號時要歸攏,調整當前位置回到左括號處 current=current->fa;//下句無法越過當前的左括號,添加該句主動升一層 while(current->x!='(')current=current->fa;//循環一直找到左括號位置 newNode->fa=current;current->right=newNode;//左括號節點的右節點是右括號 newNode=newNode->fa;//左括號調整為當前節點位置 }else if(x=='|'){//優先級在|和&下,當前位置升到緊鄰左括號或者根前 while(current->fa->x!='('&&current->fa!=root)current=current->fa;current->fa->left=newNode;newNode->fa=current->fa;//|變成當前節點父節點的左子, current->fa=newNode;newNode->left=current;//當前節點變成|的左子 }else if(x=='&'){//如果父節點是|,則&優先級高,要下潛。否則遇到&就得上浮 if(current->fa->x=='|'){current->fa->right=newNode;newNode->fa=current->fa;//當前節點的父節點變成&的父節點, current->fa=newNode;newNode->left=current;//當前節點變成&節點的左節點 }else{while(current->fa->x=='&')current=current->fa;//父是&就得上浮,得父不是&得節點為當前節點 if(current->fa->left==current)current->fa->left=newNode;//當前節點是父節點的左子,掛父節點的左樹 else current->fa->right=newNode;//掛父節點的右樹 newNode->fa=current->fa;current->fa=newNode;newNode->left=current;//當前節點(&)掛插入節點的左樹 }}current=newNode;//插入的節點變成當前節點(括號選左括號) }void clear(node* x) {// 遞歸清除節點及其子節點if (!x) return;clear(x->left);clear(x->right);delete x;}void view1(node *x){cout<<x->x;if(x->left)view1(x->left);if(x->right)view1(x->right);}void view3(node *x){if(x->left)view3(x->left);cout<<x->x;if(x->right)view3(x->right);}void view2(node *x){cout<<x->x<<"["<<x->k<<"] ";if(x->left)view2(x->left);if(x->right)view2(x->right);}bool run(node *n){bool k1,k2; //左右樹運算結果 if(n->x=='r')return n->k=run(n->left);//根和左括號處結果僅源自左樹 if(n->x=='(')return n->k=run(n->left);//右括號不影響結果 if(n->x=='0'||n->x=='1')return n->k;//運算數 if(n->x=='&'){//與運算 k1=run(n->left);//先算左樹 if(k1==0){//如果左樹是0,直接返回0,不用算右樹 n_yu++;return n->k=0;}k2=run(n->right);return n->k=k1&&k2;}if(n->x=='|'){//或運算 k1=run(n->left);if(k1==1){//如果左樹是1,直接返回1,不用算右樹 n_huo++;return n->k=1;}k2=run(n->right);return n->k=k1||k2;}}
}tree;
int main(){//freopen("expr.in","r",stdin);string s;cin>>s;for(int i=0;s[i];i++){tree.insert(s[i]); //cout<<i<<" "<<s[i]<<"先序";tree.view1(tree.root);cout<<endl;}//cout<<"先序";tree.view1(tree.root);cout<<endl;//cout<<"中序";tree.view3(tree.root);cout<<endl;cout<<tree.run(tree.root)<<endl;cout<<n_yu<<" "<<n_huo<<endl;//cout<<"先序";tree.view2(tree.root);cout<<endl;return 0;
}

思路

1.構建二叉樹,n個字符n次操作,)、|和&需要上溯,最差情況是從當前節點回溯到根節點(n次),所以時間復雜度是o(n^2),這里n=10 ^6,結果是10 ^12,大于1秒的大約次數10 ^8次。有可能會超時——還好沒有。
遍歷邏輯表達式,每個字符建立一個指針空間節點
將所有節點連接成二叉樹
經過一些樣例數據的實操,得到邏輯關系
root
開始就有,用r標記,位置不變。后繼只有左沒有右
0、1、(
添(節點,或左或右
)
上溯,找到(節點,成為(節點的右節點,父(成當前節點。
先回溯一次,避免連續右括號時停留在當前(節點
|
添節點
上溯,直到父是根r或(,當前節點變成自己的左節點,自己成父的右節點
&
添節點
父是|,則當前節點(0、1)成為自己的左節點,自己成父(|)的右節點
父是&,則上溯直到父是|或者根或(,當前節點成左節點,自己成父的右節點
2.遞歸計算。run函數,,先左右再根,后序遍歷,至多每個節點算一次O(n)。
return k=run(left)&&run(right);感覺只算左(不知道原因)
須要分別計算
k1=run(left)
k2=run(right)
&運算,左是0是短路。|運算左是1是短路。(當然另一邊也存在這種情況,但是本題說了只是左)
有10^6個節點

作圖驗證

在這里插入圖片描述

小結

冬麥需要9個月,夏玉米需要4個月。萬事萬物的生長成熟都需要足夠的時間!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90957.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90957.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90957.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從釋永信事件看“積善“與“積惡“的人生辯證法

博客目錄起心動念皆是因&#xff0c;當下所受皆是果。"起心動念皆是因&#xff0c;當下所受皆是果。"這句古老的智慧箴言&#xff0c;在少林寺方丈釋永信涉嫌違法被調查的事件中得到了令人唏噓的印證。一位本應六根清凈、持戒修行的佛門領袖&#xff0c;卻深陷貪腐丑…

圖片格式轉換

文章目錄 背景目標實現下載 背景 格式碎片化問題 行業標準差異&#xff1a;不同領域常用格式各異&#xff08;如設計界用PSD/TIFF&#xff0c;網頁用JPG/PNG/WEBP&#xff0c;系統圖標用ICO/ICNS&#xff09;。 設備兼容性&#xff1a;老舊設備可能不支持WEBP&#xff0c;專業…

Flutter實現Android原生相機拍照

方法1&#xff1a;使用Flutter的camera插件&#xff08;完整實現&#xff09; 1. 完整依賴與權限配置 # pubspec.yaml dependencies:flutter:sdk: fluttercamera: ^0.10.52path_provider: ^2.0.15 # 用于獲取存儲路徑path: ^1.8.3 # 用于路徑操作permission_handler:…

記錄幾個SystemVerilog的語法——隨機

1. 隨機穩定性(random stability)隨機穩定性是指每個線程(thread)或對象(object)的random number generator(RNG)是私有的&#xff0c;一個線程返回的隨機值序列與其他線程或對象的RNG是無關的。隨機穩定性適用于以下情況&#xff1a;系統隨機方法調用&#xff1a;$urandom()和…

初識 docker [下] 項目部署

項目部署Dockerfile構建鏡像DockerCompose基本語法基礎命令項目部署 前面我們一直在使用別人準備好的鏡像&#xff0c;那如果我要部署一個Java項目&#xff0c;把它打包為一個鏡像該怎么做呢&#xff1f; …省略一萬字 站在巨人的肩膀上更適合我們普通人,所以直接介紹兩種簡單…

Android15廣播ANR的源碼流程分析

Android15的廣播ANR源碼流程跟了下實際代碼的流程&#xff0c;大概如下哈&#xff1a;App.sendBroadcast() // 應用發起廣播→ AMS.broadcastIntentWithFeature() // 通過Binder IPC進入system_server進程→ AMS.broadcastIntentLocked() // 權限校驗廣播分類&#xff08;前…

密碼學中的概率論與統計學:從頻率分析到現代密碼攻擊

在密碼學的攻防博弈中&#xff0c;概率論與統計學始終是破解密碼的“利器”。從古典密碼時期通過字母頻率推測凱撒密碼的密鑰&#xff0c;到現代利用線性偏差破解DES的線性密碼分析&#xff0c;再到側信道攻擊中通過功耗數據的統計特性還原密鑰&#xff0c;統計思維貫穿了密碼分…

力扣刷題977——有序數組的平方

977. 有序數組的平方 題目&#xff1a; 給你一個按 非遞減順序 排序的整數數組 nums&#xff0c;返回 每個數字的平方 組成的新數組&#xff0c;要求也按 非遞減順序 排序。示例 1&#xff1a; 輸入&#xff1a;nums [-4,-1,0,3,10] 輸出&#xff1a;[0,1,9,16,100] 解釋&…

應用加速游戲盾的安全作用

在數字娛樂產業蓬勃發展的今天&#xff0c;游戲已從單純的娛樂工具演變為連接全球數十億用戶的社交平臺與文化載體。然而&#xff0c;伴隨游戲市場的指數級增長&#xff0c;網絡攻擊的頻率與復雜性也呈爆發式上升。從DDoS攻擊導致服務器癱瘓&#xff0c;到外掛程序破壞公平競技…

linux安裝zsh,oh-my-zsh,配置zsh主題及插件的方法

這是一份非常詳細的指南&#xff0c;帶你一步步在 Linux 系統中安裝 Zsh、配置主題和安裝插件。 Zsh&#xff08;Z Shell&#xff09;是一個功能強大的 Shell&#xff0c;相比于大多數 Linux 發行版默認的 Bash&#xff0c;它提供了更強的自定義能力、更智能的自動補全、更漂亮…

【設計模式系列】策略模式vs模板模式

策略模式是什么&#xff1f;如何定義并封裝一系列算法策略模式 (Strategy Pattern)模板模式 (Template Pattern)模板模式與策略模式的深度對比與區分混合使用兩種模式的場景策略模式 (Strategy Pattern) 應用場景&#xff1a;當需要根據不同條件選擇不同算法或行為時&#xff…

aigc(1.1) opensora-2.0

open sora-2.0相關鏈接: arxiv鏈接 huggingface頁面 HunyuanVideo VAE open sora2.0的VAE模型復用了HunyuanVideo的3D VAE,HunyuanVideo的arxiv鏈接。下圖來自論文,可見VAE是一個因果注意力的3D結構。在配圖左側,視頻會被編碼為video token序列,而在配圖右側,去噪的vide…

Linux驅動21 --- FFMPEG 音頻 API

目錄 一、FFMPEG 音頻 API 1.1 解碼步驟 創建核心上下文指針 打開輸入流 獲取輸入流 獲取解碼器 初始化解碼器 創建輸入流指針 創建輸出流指針 初始化 SDL 配置音頻參數 打開音頻設備 獲取一幀數據 發送給解碼器 從解碼器獲取數據 開辟數據空間 初始化內存 音頻重采樣…

《計算機“十萬個為什么”》之 [特殊字符] 序列化與反序列化:數據打包的奇妙之旅 ??

《計算機“十萬個為什么”》之 &#x1f4e6; 序列化與反序列化&#xff1a;數據打包的奇妙之旅 ??歡迎來到計算機“十萬個為什么”系列&#xff01; 本文將以「序列化與反序列化」為主題&#xff0c;深入探討計算機世界中數據的打包與解包過程。 讓我們一起解開數據的神秘面…

機器學習與深度學習評價指標

機器學習與深度學習評價指標完全指南 ?? 為什么需要評價指標? 想象你是一位醫生,需要判斷一個診斷模型的好壞。如果模型說"這個病人有癌癥",你需要知道: 這個判斷有多準確? 會不會漏掉真正的癌癥患者? 會不會誤診健康的人? 評價指標就像是給AI模型打分的&…

Hugging Face-環境配置

打開anaconda promptconda activate pytorchpip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers datasets tokenizerspycharm找到pytorch下的python.exe#將模型下載到本地調用 from transformers import AutoModelForCausalLM,AutoTokenizer#將模型和分詞工…

cnn中池化層作用

一、池化層概述 在卷積神經網絡中&#xff0c;池化層是核心組件之一&#xff0c;主要作用是逐步降低特征圖的空間尺寸即寬和高&#xff0c;從而減少計算量、控制過擬合并增強模型的魯棒性。 核心作用 降維與減少計算量 壓縮特征圖的尺寸&#xff0c;顯著減少后續層的參數數量和…

寫一個音樂爬蟲

今天我們寫一個網易云音樂的爬蟲&#xff0c;爬取網易云音樂熱歌榜音樂鏈接并下載&#xff0c;這里用到了之前引用的BeautifulSoup和requests。 BeautifulSoup是一個Python庫&#xff0c;用于從HTML和XML文件中提取數據。它提供了一種簡單的方式來遍歷文檔樹和搜索文檔樹中的元…

戰斗公式和傷害走配置文件

故事背景&#xff0c;上次屬性計算用的配置&#xff0c;這次傷害計算也走配置&#xff0c;下面是測試代碼和測試數據local formulas {[100001]{id 100001,name "基礎傷害",formula "function (self,tag,ishit,iscritial,counterratio)\n if ishit1 then\n …

線性代數 上

文章目錄線性代數知識整理一、求行列式1、 套公式2、利用性質&#xff0c;化為可套公式3、抽象行列式4、抽象向量二、代數余子式的線性組合三、求AnA^nAn四、證明A可逆五、求A的逆1、定義法2、初等變換3、公式六、求秩七、線性表示的判定八、線性無關九、求極大線性無關組十、等…