一、学习算法
(1、)hash(字符串)
概念:将任意长度的信息,转换成一种单映射,固定长度的信息,通过它去代表自己,字符串哈希是将自己转换成数字,代表自己;
方式:
进制哈希
(1)、首先定义一个进制数(base),模数(mod越大越好);
(2)、再枚举字符串的每一位(从右往左,i=(0-(n-1)),与base^i相乘加到ans(记录)去,最后对mod取模;
base和mod选的不好时就有可能产生hash冲突:两个不同的串有相同的hash值,但事实上两个串不同;
减小冲突概率采取:双hash看两个字符串是否一致,就比较两个hash值是否相等
二、刷题题解
1、# [NOIP2001 普及组] 求先序排列
## 题目描述
给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,且二叉树的节点个数 $ \le 8$)。
## 输入格式
共两行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。
## 输出格式
共一行一个字符串,表示一棵二叉树的先序。
## 样例 #1
### 样例输入 #1
```
BADC
BDCA
```
### 样例输出 #1
```
ABCD
```
## 提示
**【题目来源】**
NOIP 2001 普及组第三题
题目给定中序(左根右):BADC 后序(左右根):BDCA
通过后序可以确定根是谁即A得到新的对应关系左支前序:B 后序B 右支前序:DC 后序DC
因为是要给出前序(根左右)我们先输出根,在递归左支,和递归右支当传过来的中序没值时,直接return;
附代码
#include<bits/stdc++.h>
using namespace std;
void tree(string zx,string hx)
{if(zx.size()>0)
{char z=hx[hx.size()-1];
cout<<z;
int wz=zx.find(z);
tree(zx.substr(0,wz),hx.substr(0,wz));
tree(zx.substr(wz+1),hx.substr(wz,hx.size()-wz-1));
}
}
int main()
{string zx;
string hx;
cin>>zx;
cin>>hx;
tree(zx,hx);
}
2、# 亲戚
## 题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
## 题目描述
规定:$x$ 和 $y$ 是亲戚,$y$ 和 $z$ 是亲戚,那么 $x$ 和 $z$ 也是亲戚。如果 $x$,$y$ 是亲戚,那么 $x$ 的亲戚都是 $y$ 的亲戚,$y$ 的亲戚也都是 $x$ 的亲戚。
## 输入格式
第一行:三个整数 $n,m,p$,($n,m,p \le 5000$),分别表示有 $n$ 个人,$m$ 个亲戚关系,询问 $p$ 对亲戚关系。
以下 $m$ 行:每行两个数 $M_i$,$M_j$,$1 \le M_i,~M_j\le N$,表示 $M_i$ 和 $M_j$ 具有亲戚关系。
接下来 $p$ 行:每行两个数 $P_i,P_j$,询问 $P_i$ 和 $P_j$ 是否具有亲戚关系。
## 输出格式
$p$ 行,每行一个 `Yes` 或 `No`。表示第 $i$ 个询问的答案为“具有”或“不具有”亲戚关系。
## 样例 #1
### 样例输入 #1
```
6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6
```
### 样例输出 #1
```
Yes
Yes
No
```
这是一个简单的并查集题,我们可以用一个数组记录所有的元数,初始标记都为0;
运用路径压缩原理,给相同集合内的元素赋上相同的标记;
方式,定义一个变量x用来标记,按照题目给的值,先判断是否标记都为0,是就给这两个位置赋上变量++x;
一个是0一个不是0,就代表一个已在集合内,一个不在,将在的标记赋给不在的位置;
两个都有时,就进行两个集合的合并,改变一个集合的所有成员的标记,成另一个集合的标记,就完成了两个集合的合并;
查找时,看两个元素的标记是否一样即可;
附代码
#include<bits/stdc++.h>
using namespace std;
int jl[10000];
int x;
main()
{int n,m,p;
cin>>n>>m>>p;
while(m--)
{int y1,y2;
cin>>y1>>y2;
if(jl[y1]==0&&jl[y2]==0)
{jl[y1]=jl[y2]=++x;}
else
if(jl[y1]==0&&jl[y2]!=0)
{jl[y1]=jl[y2];}
else
if(jl[y1]!=0&&jl[y2]==0)
{jl[y2]=jl[y1];}
else
{int z=jl[y1];
for(int i=0;i<=n;i++)
if(jl[i]==z){jl[i]=jl[y2];}
}
}
while(p--)
{int y1,y2;
cin>>y1>>y2;
if((jl[y1]==jl[y2])&&(jl[y1]!=0&&jl[y2]!=0)||(y1==y2))
cout<<"Yes"<<'\n';
else
cout<<"No"<<'\n';
}
}