ACM模版——数据结构
//===========================================\\
| KMP算法 |
\\===========================================//
char p[10010],t[1000010];
int next[10010],lp,lt; // lp为p长度,lt为t长度
void getnext()
{
int i=0,j=-1;
next[0]=-1;
while ( i<lp )
{
if ( j==-1 || p[i]==p[j] )
{
i++; j++;
if ( p[i]==p[j] ) next[i]=next[j];
else next[i]=j;
}
else j=next[j];
}
}
int kmp()
{
int i=0,j=0,ans=0;
getnext();
while ( i<lt && j<lp )
{
if ( j==-1 || t[i]==p[j] ){ i++; j++; }
else j=next[j];
if ( j==lp )
{
// 位置: x0=i-j
ans++;
j=next[j];
}
}
return ans;
}
//===========================================\\
| BM算法 |
\\===========================================//
char p[10010],t[1000010];
int suff[10010],good[10010],Asc[256];
int ans,lenp,lent;
void getgood()
{
int i,j,f;
suff[lenp-1]=lenp; // 求suff
j=lenp-1;
for ( i=lenp-2; i>=0; i--)
{
if ( i>j && suff[i+lenp-1-f]<i-j )
suff[i]=suff[i+lenp-1-f];
else
{
if ( i<j ) j=i;
f=i;
while ( j>=0 && p[j]==p[j+lenp-1-f]) j--;
suff[i]=f-j;
}
}
for ( i=0; i<lenp; i++ ) good[i]=lenp; //求good
for ( i=lenp-1; i>=0; i--)
if ( suff[i]==i+1 ) //p不含已匹配串
for ( ; j<lenp-1-i; j++)
if ( good[j]==lenp ) good[j]=lenp-1-i;
for ( i=0; i<=lenp-2; i++)
good[lenp-1-suff[i]]=lenp-1-i; //p中含匹配串
}
void getbad()
{
memset(Asc,0xff,sizeof(Asc));
for (int i=0; i<lenp; i++) Asc[p[i]]=i;
}
void bm()
{
getgood();
getbad();
int i,j=0,k=0;
ans=0;
while ( j<=lent-lenp )
{
for ( i=lenp-1; i>=k && p[i]==t[i+j]; i-- );
if ( i<k )
{
// 位置:output(j);
ans++;
j+=good[0];
k=lenp-good[0];
}
else if ( Asc[t[j+lenp]]==-1 ) j+=lenp+1;
else
{
k=0;
if ( good[i]<i-Asc[t[i+j]] ) j+=i-Asc[t[i+j]];
else
{
j+=good[i];
if ( i<good[i] ) k=lenp-good[i];
else k=0;
}
}
}
}
//===========================================\\
| 堆 |
\\===========================================//
int s[1000000],clu;
bool cmp(int a,int b) //小根堆
{
return a>b;
}
void make() //make_heap(s+1,s+clu+1,cmp);
{
for (int j=clu/2; j>=1; j--)
{
int i=j,k,t=s[i];
while ( i*2<clu )
{
i*=2;
if ( i+1<clu && s[i+1]<s[i] ) k=s[++i];
else k=s[i];
if ( k<t ) s[i/2]=s[i];
else { i/=2; break; }
}
s[i]=t;
}
}
void insert(int x) //push_heap(s+1,s+clu+1,cmp);
{
int i=++clu;
while ( i!=1 && s[i/2]<x )
{
s[i]=s[i/2];
i/=2;
}
s[i]=x;
}
void del() //pop_heap(s+1,s+clu+1,cmp);
{
int i=1,j;
while ( i*2<clu )
{
i*=2;
if ( i+1<clu && s[i+1]<s[i] ) j=s[++i];
else j=s[i];
if ( j<s[clu] ) s[i/2]=s[i];
else { i/=2; break;}
}
s[i]=s[clu--];
}
//===========================================\\
| 并查集 |
\\===========================================//
int g[10000],r[10000]; //初始化g[i]=r[i]=i;
void update(int a,int b)
{
int i=g[b],j=r[g[a]];
r[g[a]]=g[b];
while ( r[i]!=i )
{
g[i]=g[a];
i=r[i];
}
g[i]=g[a];
if ( j!=g[a] ) r[i]=j;
}
//===========================================\\
| 树状数组 |
\\===========================================//
int a[100000],tr[100000],n;
int Lowbit(int t) { return t^(t-1)&t; }
int Sum(int end)
{
int ans=0;
while ( end ) { ans+=tr[end]; end-=Lowbit(end); }
return ans;
}
void update(int pos,int num)
{
int j=num-a[pos];
a[pos]=num;
while ( pos<=n ) { tr[pos]+=j; pos+=Lowbit(pos); }
}
//===========================================\\
| 二维树状数组 |
\\===========================================//
int a[10000][10000],tr[10000][10000],row,col;
int Lowbit(int t) { return t^(t-1)&t; }
int Sum(int i,int j)
{
int k,ans=0;
while ( i )
{
k=j;
while ( k ) { ans+=tr[i][k]; k-=Lowbit(k); }
i-=Lowbit(i);
}
return ans;
}
void update(int i,int j,int num)
{
int j=num-a[i][j],k;
a[i][j]=num;
while ( i<=row )
{
k=j;
while ( k<=col ) { tr[i][k]+=j; k+=Lowbit(k); }
i+=Lowbit(i);
}
}
//===========================================\\
| SBT |
\\===========================================//
struct SBT
{
int x,s,l,r; //key,size,left,right
int note; //附加信息
}tr[1000];
int stack[1000],end; // 回收删除的节点
int root,top; //树根节点、预置空间定位
void Rro(int &root) //右旋
{
int k=tr[root].l;
tr[root].l=tr[k].r;
tr[k].r=root;
tr[k].s=tr[root].s;
tr[root].s=tr[tr[root].l].s+tr[tr[root].r].s+1;
root=k;
}
void Lro(int &root) //左旋
{
int k=tr[root].r;
tr[root].r=tr[k].l;
tr[k].l=root;
tr[k].s=tr[root].s;
tr[root].s=tr[tr[root].l].s+tr[tr[root].r].s+1;
root=k;
}
void sb(int &root,bool flag) //平衡函数
{
if ( !flag ) //插入到左边
{
if ( tr[tr[tr[root].l].l].s>tr[tr[root].r].s ) Rro(root);
else if ( tr[tr[tr[root].l].r].s>tr[tr[root].r].s )
{
Lro(tr[root].l);
Rro(root);
}
else return;
}
else //插入到右边
{
if ( tr[tr[tr[root].r].r].s>tr[tr[root].l].s ) Lro(root);
else if ( tr[tr[tr[root].r].l].s>tr[tr[root].l].s )
{
Rro(tr[root].r);
Lro(root);
}
else return;
}
sb(tr[root].l,false);
sb(tr[root].r,true);
sb(root,true);
sb(root,false);
}
void insert(int &root,int x,int note)
{
if ( root==0 )
{
if ( end>0 ) root=stack[--end];
//优先实用回收站的节点
else root=++top;
tr[root].x=x;
tr[root].s=1;
tr[root].r=tr[root].l=0;
tr[root].note=note;
}
else
{
tr[root].s++;
if ( x<tr[root].x ) insert(tr[root].l,x,note);
else insert(tr[root].r,x,note);
sb(root,x>=tr[root].x);
}
}
int del(int &root,int x) //删除,stack[end++]=del()
{
tr[root].s--;
if ( x<tr[root].x ) del(tr[root].l,x);
else if ( x>tr[root].x ) del(tr[root].r,x);
else
{
if ( tr[root].l==0 || tr[root].r==0 )
{
int t=root;
root=tr[root].l+tr[root].r;
return t;
}
else
{
int t=tr[root].r;
while ( tr[t].l!=0 ) t=tr[t].l;
tr[root].x=tr[t].x;
del(tr[root].r,tr[root].x);
}
}
}
int sr(int root,int x) //查找x的位置
{
if ( x>tr[root].x && tr[root].r!=0 ) return sr(tr[root].r,x);
else if ( x<tr[root].x && tr[root].l!=0 ) return sr(tr[root].l,x);
else return root;
}
int pred(int root,int y,int x) //小于(等于)x的最大数
// 调用时 pred(root,0 ,x),空树返回0,后继也是
{
if ( root==0 ) return y;
if ( x>tr[root].x ) //加上等号,就是小于等于
return pred(tr[root].r,root,x);
else return pred(tr[root].l,y,x);
}
int succ(int root,int y,int x) //大于(等于)x的最小数
{
if ( root==0 ) return y;
if ( x<tr[root].x ) return succ(tr[root].l,root,x);
else return succ(tr[root].r,y,x);
}
int rank(int root,int x) // x的升序排名
{
if ( root==0 ) return 1;
else if ( x>tr[root].x ) return rank(tr[root].r,x)+tr[tr[root].l].s+1;
else return rank(tr[root].l,x);
}
int select(int root,int k) //找第k小的元素
{
if ( k==tr[tr[root].l].s+1 ) return root;
else if ( k<=tr[tr[root].l].s ) return select(tr[root].l,k);
else return select(tr[root].r,k-tr[tr[root].l].s-1);
}
int getmin(int root) //最小值
{
while ( tr[root].l ) root=tr[root].l;
return tr[root].x;
}
int geimax(int root) //最大值
{
while ( tr[root].r ) root=tr[root].r;
return tr[root].x;
}
//===========================================\\
| 线段树 |
\\===========================================//
struct seg_tree
{
int l,r;
int sum,mim,max,x;
}tr[100];
void build(int l,int r,int p) //建树,并初始化
{
if ( l==r )
{
tr[p].l=tr[p].r=l;
// sum=min=max=x=?
}
else
{
tr[p].l=l;
tr[p].r=r;
build(l,(l+r)/2,p*2);
build((l+r)/2+1,r,p*2+1);
// sum,min,max=?
}
}
void pushdown(int p) // 标记下传框架
{
tr[p*2].m+=tr[p].m;
tr[p*2].max+=tr[p].m;
tr[p*2+1].m+=tr[p].m;
tr[p*2+1].max+=tr[p].m;
tr[p].m=0;
}
void update(int p) // 更新框架
{
if ( tr[p*2].max>=tr[p*2+1].max )
{
tr[p].max=tr[p*2].max;
tr[p].id=tr[p*2].id;
}
else
{
tr[p].max=tr[p*2+1].max;
tr[p].id=tr[p*2+1].id;
}
}
void query(int l,int r,int p) //查询区间框架
{
if ( l<=tr[p].l && tr[p].r<=r )
{
...... // 根据标记,更新结果
return;
}
Push_Down(p);
int mid=(tr[p].l+tr[p].r)/2;
if ( l<=mid ) query(l,r,p*2);
if ( r>mid ) query(l,r,p*2+1);
// 有时候需要汇总
}
void change(int l,int r,int p) //修改区间框架
{
if ( l<=tr[p].l && tr[p].r<=r )
{
...... // 修改当前结点信息,并标上标记
return;
}
Push_Down(p);
int mid=(tr[p].l+tr[p].r)/2;
if ( l<=mid ) change(l,r,p*2);
if ( r>mid ) change(l,r,p*2+1);
Update(p); //维护当前结点信息(子结点可能被修改)
}
//===========================================\\
| 字符哈希 |
\\===========================================//
int BKDR(char *s)
{
unsigned long h=0,g=131; // 31,131,1313,13131..
while ( *s ) h=h*g+*s++;
return h%10007; // 根据实际要求取模
}
int ELF(char *s)
{
unsigned long h=0;
while ( *s )
{
h=(h<<4)+*s++;
unsigned long g=h & 0Xf0000000L;
if ( g ) h^=g>>24;
h&=~g;
}
return h%10007;
}
浙公网安备 33010602011771号