1.邻接表
用邻接表存储有向图
//加入有向边(x,y),权值为z
void add(int x,int y,int z)
{
ver[++tot]=y,edge[tot]=z,ne[tot]=h[x],h[x]=tot;
}
//访问x出发的所有边
for(int i=h[x];i;i=ne[i]){
int y=ver[i],z=edge[i];
}
2.字符串哈希
#define rep(i,a,b) for (register int i=a;i<b;++i)
#define per(i,a,b) for (register int i=a;i>b;--i)
typedef unsigned long long ULL;
const int N=1e6+10;
char s[N];
ULL f[N],p[N];
int h=13331; //h=131
ULL cal(int l,int r) //hash:s[l~r]
{
return f[r]-f[l-1]*p[r-l+1];
}
void init()
{
p[0]=1;
int len=strlen(s+1);
rep(i,1,len+1){
f[i]=f[i-1]*h+s[i]-'a'+1;
p[i]=p[i-1]*h;
}
}
3.kmp
ne数组
ne[1]=0;
int j=0;
rep(i,2,n+1){
while(j>0&&a[i]!=a[j+1]) j=ne[j];
if(a[i]==a[j+1]) ++j;
ne[i]=j;
}
f数组
int j=0;
rep(i,1,m+1){
while(j>0&&(j==n||b[i]!=a[j+1])) j=ne[j];
if(b[i]==a[j+1]) ++j;
f[i]=j;
}
4.trie树
int tr[N][26],tot=1,cnt[M];
string s;
void ins()
{
int p=1;
for(auto i:s){
int ch=i-'a';
if(tr[p][ch]==0) tr[p][ch]=++tot;
p=tr[p][ch];
}
++cnt[p];
}
int search()
{
int p=1;
for(auto i:s){
int ch=i-'a';
p=tr[p][ch];
if(p==0) return 0;
}
return cnt[p];
}
5.二叉堆
int h[N],n;
void up(int p)
{
while(p>1){
if(h[p]>h[p/2]) swap(h[p],h[p/2]),p/=2;
else break;
}
}
void down(int p)
{
int s=2*p;
while(s<=n){
if(s<n&&h[s]<h[s+1]) ++s;
if(h[s]>h[p]) swap(h[s],h[p]),p=s,s=2*p;
else break;
}
}
void ins(int val)
{
h[++n]=val;
up(n);
}
void extract()
{
h[1]=h[n--];
down(1);
}
void remove(int k)
{
h[k]=h[n--];
up(k),down(k);
}