学大伟业 Day 3 培训总结

今天讲的字符串:

不多说,直接看题

一.表达式求值

题目大意:

输入一行一个表达式,计算其答案 表达式包含非负整数、加减乘除、括号

两种做法

·栈

·表达式树

这里更推荐表达式树,因为栈是先压进去,逆序操作。在进行逆序操作时即从右往左计算,实际应该是从左往右计算,所以会出现计算不符合顺序的问题。从而出现错误。

而表达式树则又称为“表达式目录树”,以数据形式表示语言级代码,它是一种抽象语法树或者说是一种数据结构。——摘自百度百科

可见,每个父节点都是一种运算符,子节点为数字。运算时从底层向上层依次按父节点符号操作子节点即可。

先贴的代码:

 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 }

隐约雷鸣,阴霾天空,但盼风雨来,能留你在此。

隐约雷鸣,阴霾天空,即使天无雨,我亦留此地。

原文地址:https://www.cnblogs.com/MisakaAzusa/p/8470377.html