算法知识补充2
一部分:Tire树:高效地存储和查找字符串集合的数据结构acwing835
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
int son[N][26],cnt[N],idx;
char str[N];
void insert(char str[]){int p=0;for(int i=0;str[i];i++){int u=str[i]-'a';if(!son[p][u])son[p][u]=++idx;p=son[p][u];}cnt[p]++;
}
int query(char str[]){int p=0;for(int i=0;str[i];i++){int u=str[i]-'a';if(!son[p][u])return 0;p=son[p][u];}return cnt[p];
}
int main(){int n;cin>>n;while(n--){char op[2];cin>>op>>str;if(op[0]=='I')insert(str);else cout<<query(str)<<endl;}return 0;
}
acwing143
二部分:并查集:1合并集合 2询问两个元素是否在一个集合acwing836
#include<iostream>
using namespace std;
const int N=100010;
int f[N];
int n,m;
int find(int x){//返回x的祖宗节点+路径压缩优化 if(f[x]!=x) f[x]=find(f[x]);return f[x];
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++)f[i]=i;while(m--){char op[2];int a,b;cin>>op;cin>>a>>b;if(op[0]=='M')f[find(a)]=find(b);else{if(find(a)==find(b))cout<<"Yes"<<endl;else cout<<"No"<<endl;}}
}
acwing837
#include<iostream>
using namespace std;
const int N=100010;
int f[N],size[N];
int n,m;
int find(int x){//返回x的祖宗节点+路径压缩优化 if(f[x]!=x) f[x]=find(f[x]);return f[x];
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){f[i]=i;size[i]=1;}while(m--){char op[5];int a,b;cin>>op;if(op[0]=='C'){cin>>a>>b;if(find(a)==find(b))continue;size[find(b)]+=size[find(a)];f[find(a)]=find(b);}else if(op[1]=='1'){cin>>a>>b;if(find(a)==find(b))cout<<"Yes"<<endl;else cout<<"No"<<endl;}else {cin>>a;cout<<size[find(a)]<<endl;}}return 0;
}
acwing240
#include<iostream>
using namespace std;
const int N=50010;
int n,m;
int f[N],d[N];
int find(int x){if(f[x]!=x){int t=find(f[x]);d[x]+=d[f[x]];f[x]=t;}return f[x];
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++)f[i]=i;int t,x,y;int res=0;while(m--){cin>>t>>x>>y;if(x>n||y>n)res++;else{int fx=find(x),fy=find(y);if(t==1){if(fx==fy&&(d[x]-d[y])%3)res++;else if(fx!=fy){f[fx]=fy;d[fx]=d[y]-d[x];}}else{if(fx==fy&&(d[x]-d[y]-1)%3)res++;else if(fx!=fy){f[fx]=fy;d[fx]=d[y]+1-d[x];}}}}cout<<res<<endl;return 0;
}
三部分:手写堆
#include<iostream>
using namespace std;
const int N=100010;
int n,m;
int h[N],size;
void down(int u){int t=u;if(u*2<=size&&h[u*2]<h[t])t=u*2;if(u*2+1<=size&&h[u*2+1]<h[t])t=u*2+1;if(u!=t){swap(h[u],h[t]);down(t);}
}
void up(int u){while(u/2&&h[u/2]>h[u]){swap(h[u/2],h[u]);u/=2;}
}
int main(){cin>>n;for(int i=1;i<=n;i++)cin>>h[i];size=n;for(int i=n/2;i;i--)down(i);while(m--){cout<<h[1]<<" ";h[1]=h[size];size--;down(1);}return 0;
}
acwing839
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
int n,m;
int h[N],hp[N],ph[N],size;//hp[k]表示k存的数组位置的下标i,ph[i]指这个下标在数组的位置
void heap_swap(int a,int b){swap(ph[hp[a]],ph[hp[b]]);swap(hp[a],hp[b]);swap(h[a],h[b]);
}
void down(int u){int t=u;if(u*2<=size&&h[u*2]<h[t])t=u*2;if(u*2+1<=size&&h[u*2+1]<h[t])t=u*2+1;if(u!=t){heap_swap(u,t);down(t);}
}
void up(int u){while(u/2&&h[u/2]>h[u]){heap_swap(u/2,u);u/=2;}
}
int main(){cin>>n;while(n--){char op[10];int k,x;cin>>op;if(!strcmp(op,"I")){cin>>x;size++;m++;//记录第几次插入 ph[m]=size,hp[size]=m;//每次插入都是在堆尾插入 h[size]=x;//记录插入的值 up(size);}else if(!strcmp(op,"PM"))cout<<h[1]<<endl;else if(!strcmp(op,"DM")){heap_swap(1,size);size--;down(1);}else if(!strcmp(op,"D")){cin>>k;k=ph[k];//保存当前被删除节点的下标 heap_swap(k,size);//第m个插入的元素移到了堆尾,此时ph[m]指向堆尾 size--;//删除堆尾 down(k);up(k);//k是之前记录被删除的节点的下标 }else {cin>>k>>x;k=ph[k];h[k]=x;down(k),up(k);}}return 0;
}