首页 > 代码库 > 比赛用模板
比赛用模板
后缀自动机
//确认maxn大小,一般是原字符串长度最大值的2倍,然后是init(),最后是一个一个的字符插入,//转化成对应的数字,调用Insert函数,可支持在线。struct SAM{ int ch[maxn][26]; int pre[maxn],step[maxn]; int last,id; void init() { last=id=0; memset(ch[0],-1,sizeof(ch[0])); pre[0]=-1; step[0]=0; } void Insert(int c) { int p=last,np=++id; step[np]=step[p]+1; memset(ch[np],-1,sizeof(ch[np])); while(p!=-1&&ch[p][c]==-1) ch[p][c]=np,p=pre[p]; if(p==-1) pre[np]=0; else { int q=ch[p][c]; if(step[q]!=step[p]+1) { int nq=++id; memcpy(ch[nq],ch[q],sizeof(ch[q])); step[nq]=step[p]+1; pre[nq]=pre[q]; pre[np]=pre[q]=nq; while(p!=-1&&ch[p][c]==q) ch[p][c]=nq,p=pre[p]; } else pre[np]=q; } last=np; /* //查询出现至少K次的子串数量 while(np!=-1&&num[np]<K) //没有达到K次的就加1 { num[np]++; if(num[np]>=K) ans+=step[np]-step[pre[np]]; //加上答案 np=pre[np]; } */ } /* int GetCnt() //可查询有多少种不同的子串 { int ret=0; for(int i=id;i>=1;i--) ret+=step[i]-step[pre[i]]; return ret; } */}sam;
多个字符串最长公共子串(后缀自动机)
/*题意:给若干个字符串,长度不超过100000,求最长公共连续字串解析:后缀自动机,对输入的第一个字符串建一个后缀自动机,在sam中添加两个量Max[i](查询时以第i个节点为最后一个字符的后缀的最大长度),Min[i](所有查询Max[i]中的最小值)。*/#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<vector>#include<cmath>using namespace std;const int maxn=200005;struct SAM{ int ch[maxn][26]; int pre[maxn],step[maxn]; int last,id; int Min[maxn],Max[maxn]; void init() //初始化 { last=id=0; memset(ch[0],-1,sizeof(ch[0])); pre[0]=-1; step[0]=0; Min[0]=Max[0]=0; } void Insert(int c) //模板,自己百度 { int p=last,np=++id; step[np]=step[p]+1; memset(ch[np],-1,sizeof(ch[np])); Min[np]=Max[np]=step[np]; while(p!=-1&&ch[p][c]==-1) ch[p][c]=np,p=pre[p]; if(p==-1) pre[np]=0; else { int q=ch[p][c]; if(step[q]!=step[p]+1) { int nq=++id; memcpy(ch[nq],ch[q],sizeof(ch[q])); step[nq]=step[p]+1; Min[nq]=Max[nq]=step[nq]; pre[nq]=pre[q]; pre[np]=pre[q]=nq; while(p!=-1&&ch[p][c]==q) ch[p][c]=nq,p=pre[p]; } else pre[np]=q; } last=np; } void Find(char *S) { int len=strlen(S); int u=0,d=0; for(int i=0;i<=id;i++) Max[i]=0; for(int i=0;i<len;i++) { int c=S[i]-‘a‘; if(ch[u][c]!=-1) d++,u=ch[u][c]; else { while(u!=-1&&ch[u][c]==-1) u=pre[u]; if(u!=-1) d=step[u]+1,u=ch[u][c]; else u=0,d=0; } Max[u]=max(Max[u],d);//更新 } for(int i=id;i>=1;i--) Max[pre[i]]=max(Max[pre[i]],Max[i]); for(int i=0;i<=id;i++) Min[i]=min(Min[i],Max[i]); } int GetAns() { int ret=0; for(int i=0;i<=id;i++) ret=max(ret,Min[i]); return ret; }}sam;char S[maxn];int main(){ scanf("%s",S); int len=strlen(S); sam.init(); for(int i=0;i<len;i++) sam.Insert(S[i]-‘a‘); while(scanf("%s",S)!=EOF) sam.Find(S); printf("%d\n",sam.GetAns()); return 0;}
二分图匹配模板
//maxn,n取二分图两方中点数的最大值,首先init,然后在输入中加边AddEdge,//最后调用solvestruct edge{ int v,next;}E[2*maxn];struct TwoMatch{ int head[maxn],eid; bool vis[maxn]; int n,To[maxn]; void init(int nn) { n=nn; eid=0; for(int i=1;i<=n;i++) head[i]=-1; } void AddEdge(int u,int v) { E[++eid].v=v; E[eid].next=head[u]; head[u]=eid; } bool dfs(int u) { for(int i=head[u];i!=-1;i=E[i].next) { int v=E[i].v; if(vis[v]) continue; vis[v]=true; if(To[v]==-1||dfs(To[v])) { To[v]=u; return true; } } return false; } int solve() { int ans=0; for(int i=1;i<=n;i++) To[i]=-1; for(int i=1;i<=n;i++) { memset(vis,false,sizeof(vis)); if(dfs(i)) ans++; } return ans; }}tm;
单调栈
int rear=0;for(int st=1;st<=N;st++){ while(rear>0&&H[que[rear]]>=H[st]) --rear; if(rear==0) le[st]=0; else le[st]=que[rear]; que[++rear]=st; }
单调队列
int que[maxn],elem[maxn]; int f=1,r=0; for(int i=1;i<K;i++) { while(r>=f&&elem[que[r]]>=elem[i]) --r; que[++r]=i; } for(int i=K;i<=N;i++) { while(r>=f&&elem[que[r]]>=elem[i]) --r; que[++r]=i; while(que[f]+K<=i) ++f; MIN[i-K]=elem[que[f]]; }
比赛用模板
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。