码迷,mamicode.com
首页 > 其他好文 > 详细

比赛用模板

时间:2016-09-12 14:26:20      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

后缀自动机

技术分享
//确认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,
//最后调用solve
struct 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

 

比赛用模板

标签:

原文地址:http://www.cnblogs.com/wust-ouyangli/p/5864509.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!