學大偉業 Day 3 培訓總結
阿新 • • 發佈:2018-02-25
比較 cas 錯誤 idt mod har 質數 jpg OS
今天講的字符串:
不多說,直接看題
一.表達式求值
題目大意:
輸入一行一個表達式,計算其答案 表達式包含非負整數、加減乘除、括號
兩種做法
·棧
·表達式樹
這裏更推薦表達式樹,因為棧是先壓進去,逆序操作。在進行逆序操作時即從右往左計算,實際應該是從左往右計算,所以會出現計算不符合順序的問題。從而出現錯誤。
而表達式樹則又稱為“表達式目錄樹”,以數據形式表示語言級代碼,它是一種抽象語法樹或者說是一種數據結構。——摘自百度百科
可見,每個父節點都是一種運算符,子節點為數字。運算時從底層向上層依次按父節點符號操作子節點即可。
先貼棧的代碼:
1 /* 2 1+(2+3)*4 321 4 */ 5 6 #include <iostream> 7 #include <stack> 8 using namespace std; 9 10 const int MAXN = 10000 + 10; 11 char str[MAXN]; 12 stack<int> nums; 13 stack<char> symbol; 14 15 void pop() 16 { 17 int a = nums.top();nums.pop(); 18 int b = nums.top();nums.pop(); 19 chars = symbol.top();symbol.pop(); 20 int ans; 21 switch(s) 22 { 23 case ‘+‘:ans=a+b;break; 24 case ‘-‘:ans=b-a;break; 25 case ‘*‘:ans=a*b;break; 26 case ‘/‘:ans=b/a;break; 27 } 28 nums.push(ans); 29 } 30 int main() 31 { 32 cin >> (str+1); 33 for(int i=1;str[i]!=0;i++) 34 { 35 char c=str[i]; 36 if(‘0‘<=c&&c<=‘9‘) 37 { 38 nums.push(c-‘0‘); 39 } else { 40 if(c==‘)‘) 41 { 42 while(symbol.top() != ‘(‘) pop(); 43 symbol.pop(); 44 } else if (c==‘+‘ || c==‘-‘) 45 { 46 while(!symbol.empty() 47 &&symbol.top()!=‘+‘ 48 &&symbol.top()!=‘-‘ 49 &&symbol.top()!=‘(‘) pop(); 50 symbol.push(c); 51 } else symbol.push(c); 52 } 53 } 54 while(!symbol.empty())pop(); 55 cout<<nums.top()<<endl; 56 57 return 0; 58 }
在計算上面圖中的例子時,棧會出錯。
下面給出表達式樹的代碼:
1 /* 2 10+(2+3)*4 3 30 4 */ 5 6 #include <iostream> 7 #include <stack> 8 #include <cstring> 9 using namespace std; 10 11 const int MAXN = 10000 + 10; 12 char str[MAXN]; 13 14 int solve(int l, int r) 15 { 16 17 int pos=-1; 18 int flag=0; 19 int level=2; // 0:+- 1:*/ 20 for(int i=l;i<=r;i++) 21 { 22 if(str[i]==‘(‘)flag++; 23 if(str[i]==‘)‘)flag--; 24 if(flag == 0 && (str[i]<‘0‘||str[i]>‘9‘||str[i]==‘+‘||str[i]==‘-‘||str[i]==‘*‘||str[i]==‘/‘)&&str[i]!=‘)‘) 25 { 26 int l=-1; 27 switch(str[i]) 28 { 29 case ‘+‘:case ‘-‘:l=0;break; 30 case ‘*‘:case ‘/‘:l=1;break; 31 } 32 if(level >= l) 33 { 34 level=l; 35 pos=i; 36 } 37 } 38 } 39 if(pos==-1) 40 { 41 if(str[l]==‘(‘&&str[r]==‘)‘) return solve(l+1,r-1); 42 int x=0; 43 for(int i=l;i<=r;i++) 44 x=x*10+str[i]-‘0‘; 45 return x; 46 } 47 int a = solve(l, pos-1); 48 int b = solve(pos+1, r); 49 int ans; 50 switch(str[pos]) 51 { 52 case ‘+‘:ans=a+b;break; 53 case ‘-‘:ans=a-b;break; 54 case ‘*‘:ans=a*b;break; 55 case ‘/‘:ans=a/b;break; // 3*2/3 56 } 57 return ans; 58 } 59 int main() 60 { 61 cin >> (str+1); 62 cout << solve(1, strlen(str+1)) << endl; 63 64 return 0; 65 }
二.字符串統計
題目大意:給定N個字符串,判斷不同的字符串有多少個。
做法:hash
所謂hash就是把每個字符串設成一個值,每個字符串的值要不同,所以操作的時候只要弄的奇奇怪怪就好啦(個人理解,不喜勿噴)
這樣比較字符串就成了比較數值的問題。
哈希碰撞:所謂哈希碰撞是指在哈希時難免會遇到有重復的數值,解決方案可以為雙哈希。
例如:在哈希時會模一個很大的質數,假設這個質數為mod,當遇到某個數m時(m<mod)m % mod = m
但是當遇到另一個數n時,n恰巧為 m + mod 那麽 n % mod = m 兩串字符對應值都為m,產生了碰撞。
在洛谷有道模板題,鏈接:https://www.luogu.org/problemnew/show/P3370
hash代碼如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 long n; 7 char s[10001]; 8 long long ms[10101]={0}; 9 long long ans=1; 10 11 int main() 12 { 13 scanf("%d",&n); 14 for(int i=1;i<=n;i++) 15 { 16 cin>>s; 17 18 int len=strlen(s); 19 for(int j=0;j<len;j++) 20 ms[i]=(ms[i]*131+(long long)s[j])%233333333333+233317; 21 22 } 23 sort(ms+1,ms+n+1); 24 for(int i=1;i<n;i++) 25 { 26 if(ms[i]!=ms[i+1]) 27 ans++; 28 } 29 printf("%d",ans); 30 31 32 }
學大偉業 Day 3 培訓總結