首页 > 代码库 > 比赛用模板

比赛用模板

后缀自动机

技术分享
//确认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;
View Code

多个字符串最长公共子串(后缀自动机)

技术分享
/*题意:给若干个字符串,长度不超过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;}
View Code

二分图匹配模板

技术分享
//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;
View Code

单调栈

技术分享
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; }
View Code

单调队列

技术分享
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]];    }
View Code

 

比赛用模板