1. 程式人生 > >學大偉業 Day 3 培訓總結

學大偉業 Day 3 培訓總結

比較 cas 錯誤 idt mod har 質數 jpg OS

今天講的字符串:

不多說,直接看題

一.表達式求值

題目大意:

輸入一行一個表達式,計算其答案 表達式包含非負整數、加減乘除、括號

兩種做法

·棧

·表達式樹

這裏更推薦表達式樹,因為棧是先壓進去,逆序操作。在進行逆序操作時即從右往左計算,實際應該是從左往右計算,所以會出現計算不符合順序的問題。從而出現錯誤。

而表達式樹則又稱為“表達式目錄樹”,以數據形式表示語言級代碼,它是一種抽象語法樹或者說是一種數據結構。——摘自百度百科

技術分享圖片

可見,每個父節點都是一種運算符,子節點為數字。運算時從底層向上層依次按父節點符號操作子節點即可。

先貼的代碼:

 1 /*
 2 1+(2+3)*4
 3
21 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 char
s = 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 培訓總結