并查集:
模板1
int find(int x)
{
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
模板2
int find(int x)
{
int tem=x,pan;
while(x!=f[x])
{
x=f[x];
}
while(tem!=f[tem])
{
pan=tem;
tem=f[pan];
f[pan]=x;
}
return x;
}
逆元模板:
#include<stdio.h>
long long ex_gcd(long long a,long long b,long long &x,long long &y)//扩展欧几里得(扩展gcd)
{
if (a==0&&b==0) return -1;
if (b==0)
{
x=1;
y=0;
return a;
}
long long d=ex_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
long long mod_inverse(long long a,long long n)//乘法逆元
{
long long x,y;
long long d = ex_gcd(a,n,x,y);
return (x%n+n)%n;
}
KMP:
void kmp()
{
int j=0;
for(int i=1;i<=m;)
{
if(j==0||T[i]==T[j])
{
nextt[++i]=++j;
}
else
j=nextt[j];
}
}
最大最小表示法模板:
char a[1000010];
int posmin(int len)//最小表示法
{
int i=0,j=1,k=0;
while(i<len&&j<len&&k<len)
{
int pan=a[(i+k)%len]-a[(j+k)%len];
if(pan==0)
k++;
else
{
if(pan>0)
i+=k+1;
else
j+=k+1;
if(i==j)
j++;
k=0;
}
}
return min(i+1,j+1);
}
int posmax(int len)//最大表示法
{
int i=0,j=1,k=0;
while(i<len&&j<len&&k<len)
{
int pan=a[(i+k)%len]-a[(j+k)%len];
if(pan==0)
k++;
else
{
if(pan>0)
j+=k+1;
else
i+=k+1;
if(i==j)
j++;
k=0;
}
}
return min(i+1,j+1);
}
Manacher:
#include<algorithm>
#include<string.h>
#include<stdio.h>
#define M 110010
#define inf 0x3f3f3f
using namespace std;
char a[M],b[2*M];
int iny[M*2];
void init_manacher()
{
int len=strlen(a);
int l=0;
b[l++]='^';
b[l++]='#';
for(int i=0; i<len; i++)
{
b[l++]=a[i];
b[l++]='#';
}
b[l++]='!';
}
int manacher()
{
int len=strlen(a);
memset(iny,0,sizeof(iny));
int mi=0,di=0,ans=0;
for(int i=0; i<=len*2; i++)
{
if(mi>i)
iny[i]=min(mi-i,iny[2*di-i]);
else
iny[i]=1;
while(b[iny[i]+i]==b[i-iny[i]])iny[i]++;
if(iny[i]+i>mi)
{
mi=iny[i]+i;
di=i;
}
ans=max(ans,iny[i]-1);
}
return ans;
}
int main()
{
while(~scanf("%s",a))
{
init_manacher();
printf("%d\n",manacher());
}
}
指针字典树:HDU - 1251
#include<stdio.h>
#include<algorithm>
#include<string.h>'
#define inf 0x3f3f3f
using namespace std;
struct Trie
{
int v;
Trie *next[26];
};
Trie root;
char a[15];
void create_Tire(char *str)
{
Trie *p=&root,*q;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int di=str[i]-'a';
if(p->next[di]==NULL)
{
q=(Trie *)malloc(sizeof(Trie));
q->v=1;
for(int i=0;i<26;i++)
q->next[i]=NULL;
p->next[di]=q;
p=q;
}
else
{
p=p->next[di];
p->v++;
}
}
}
int find_Tire(char *str)
{
int len=strlen(a);
Trie *p=&root,*q;
for(int i=0;i<len;i++)
{
int di=str[i]-'a';
if(p->next[di]==NULL)
return 0;
p=p->next[di];
}
return p->v;
}
int main()
{
while(gets(a),a[0]!='\0')
{
create_Tire(a);
}
while(~scanf("%s",a))
{
printf("%d\n",find_Tire(a));
}
}
指针字典树释放:
void clear_Trie(Trie *p)
{
for(int i=0; i<26; i++)
{
if(p->next[i]!=NULL)
{
clear_Trie(p->next[i]);
p->next[i]=NULL;
}
}
if(p!=&root)
free(p);
}
数组模拟字典树: HDU - 1251
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
int trie[1000000][26];
int book[1000000];
char a[15];
int tot;
void create_Trie(char *str)
{
int root=0;
while(*str)
{
int di=*str-'a';
if(trie[root][di]==0)
trie[root][di]=++tot;
root=trie[root][di];
book[root]++;
str++;
}
}
int find_Trie(char *str)
{
int root=0;
while(*str)
{
int di=*str-'a';
if(trie[root][di]==0)
{
return 0;
}
root=trie[root][di];
str++;
}
return book[root];
}
int main()
{
tot=0;
while(gets(a),a[0]!='\0')
{
create_Trie(a);
}
while(~scanf("%s",a))
{
printf("%d\n",find_Trie(a));
}
}
AC自动机指针模板: HDU 2222
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
char a[70],s[1000010];
struct node
{
int v;
node *next[26];
node *fail;
};
node root;
node *que[1000010];
int cut;
void init(node *q)
{
for(int i=0; i<26; i++)
{
q->next[i]=NULL;
}
q->v=0;
q->fail=NULL;
}
void Trie_creat(char *str)
{
node *p=&root,*q;
while(*str)
{
int di=*str-'a';
if(p->next[di]==NULL)
{
q=(node *)malloc(sizeof(node));
init(q);
p->next[di]=q;
}
p=p->next[di];
str++;
}
p->v++;
}
void init_AC_automatiom()
{
int head=0,tail=0;
que[tail++]=&root;
node *temp,*p;
while(head<tail)
{
temp=que[head++];
for(int i=0;i<26;i++)
{
if(temp->next[i])
{
if(temp==&root)
{
temp->next[i]->fail=&root;
}
else
{
p=temp->fail;
while(p)
{
if(p->next[i])
{
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL)temp->next[i]->fail=&root;
}
que[tail++]=temp->next[i];
}
}
}
}
int AC_automation(char *str)
{
node *p=&root,*temp;
while(*str)
{
int di=*str-'a';
while(p->next[di]==NULL&&p!=&root)p=p->fail;
p=p->next[di];
if(!p)p=&root;
temp=p;
while(temp!=&root)
{
if(temp->v>=0)
{
cut+=temp->v;
temp->v=-1;
}
else break;
temp=temp->fail;
}
str++;
}
}
int main()
{
int n,t;
scanf("%d",&t);
while(t--)
{
init(&root);
cut=0;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%s",a);
Trie_creat(a);
}
init_AC_automatiom();
scanf("%s",s);
AC_automation(s);
printf("%d\n",cut);
}
}
AC自动机数组模拟模板 HDU 2896
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<queue>
#define M 100010
using namespace std;
int Trie[M][130],v[M],tot,n,m,fail[M],vis[M],ans[510],bp;
char a[10010];
queue<int>q;
void Trie_creat(char *str,int x)
{
int p=0;
while(*str)
{
int di=*str;
if(!Trie[p][di])
{
Trie[p][di]=++tot;
}
p=Trie[p][di];
str++;
}
v[p]=x;
}
void init_fail()
{
q.push(0);
int p;
while(!q.empty())
{
p=q.front();
q.pop();
for(int i=0;i<130;i++)
{
if(Trie[p][i])
{
int tem=fail[p];
while(tem>=0)
{
if(Trie[tem][i])
{
fail[Trie[p][i]]=Trie[tem][i];
break;
}
tem=fail[tem];
}
q.push(Trie[p][i]);
}
}
}
}
int AC_automation(char *str)
{
int p=0;
while(*str)
{
int di=*str;
while(!Trie[p][di]&&p!=0)p=fail[p];
p=Trie[p][di];
int temp=p;
while(temp&&vis[temp]>=0)
{
if(v[temp])
{
ans[bp++]=v[temp];
}
vis[temp]=-1;
temp=fail[temp];
}
str++;
}
}
int main()
{
int pp=0;
scanf("%d",&n);
tot=0;
fail[0]=-1;
for(int i=1; i<=n; i++)
{
scanf("%s",a);
Trie_creat(a,i);
}
init_fail();
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
bp=0;
scanf("%s",a);
memset(vis,0,sizeof(vis));
AC_automation(a);
if(bp>0)
{
sort(ans,ans+bp);
printf("web %d:",i);
for(int i=0;i<bp;i++)
{
printf(" %d",ans[i]);
}printf("\n");
pp++;
}
}printf("total: %d\n",pp);
}
位运算加速的gcd:
int gcd(int a,int b)
{
while(b^=a^=b^=a%=b);
return a;
}
网络流模板:
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstdio>
#define For(a,b,c) for(a=b;a<=c;a++)
#include<queue>
#define inf 999999999
using namespace std;
const int maxn = 1010;
int rong[510][510],liu[510][510];
int p[maxn];
int m,n;
int pre[maxn];
int sum;
void internet(){
queue<int> q;
while(1){//不断通过bfs来找增光路,然后ans+=增光路上的流量。
int i,j;
memset(p,0,sizeof(p));
p[1]=inf;//这里的p数组有两个作用,一是用来标记是非访问过,其次是用来记增广路上的瓶颈。
q.push(1);
while(!q.empty()){
int ans=q.front();
q.pop();
For(i,1,n){
if(!p[i]&&liu[ans][i]<rong[ans][i]){
p[i]=min(p[ans],rong[ans][i]-liu[ans][i]);
pre[i]=ans;//记录增广路。
q.push(i);
}
}
}
if(!p[n]){
break;//如果n点找不到增光路,说明已经没增广路到汇点了。
}
sum+=p[n];
int tmp=n;
while(pre[tmp]){//不断调整流量大小。
liu[pre[tmp]][tmp]+=p[n];
liu[tmp][pre[tmp]]-=p[n];
tmp=pre[tmp];
}
}
}
int main(){
int i,j,k;
int x,y,z;
while(scanf("%d%d",&m,&n)!=EOF){
sum=0;
memset(pre,0,sizeof(pre));
memset(rong,0,sizeof(rong));
memset(liu,0,sizeof(liu));
For(i,1,m){
scanf("%d%d%d",&x,&y,&z);
rong[x][y]+=z;
}
internet();
printf("%d\n",sum);
}
return 0;
}