zoukankan      html  css  js  c++  java
  • 别人的后缀自动机

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define INF 0x3f3f3f3f
    #define LNF 0x3f3f3f3f3f3f3f3f
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define pqueue priority_queue
    #define NEW(a,b) memset(a,b,sizeof(a))
    const double pi=4.0*atan(1.0);
    const double e=exp(1.0);
    const int maxn=4e5+8;
    typedef long long LL;
    typedef unsigned long long ULL;
    const LL mod=1e9+7;
    const ULL base=1e7+7;
    const int maxp=26+5;
    using namespace std;
    struct Suffix_Node{
        int ch[maxp],par,len;
        void init(){
            NEW(ch,0);
            par=len=0;
        }
    };
    LL f[maxn];//用来求子串个数开的数组
    class Suffix_Automation{
    private:
        Suffix_Node s[maxn];
        int cur,las,siz,crp;
    public:
        Suffix_Automation():las(1),cur(1),siz(1),crp(1){}
        const void init(){
            for(int i=0;i<=siz;i++) s[i].init();
            las=cur=siz=crp=1;
        }
        const int match(const char c)const{
            return s[crp].ch[c-'a'];
        }
        const void withdraw(const int len){//撤掉开头几个字母,使已匹配的剩下长度为len
            while(crp!=0&&s[s[crp].par].len>=len) crp=s[crp].par;
            if(crp==0) crp=1;
        }
        const void Transfer(const int len,const char c){//匹配字符加上c保持长度为len
            crp=s[crp].ch[c-'a'];
            if(crp==0) crp=1;
            withdraw(len);
        }
        const void ex_tend(const char c){//扩展新字符
            int x=c-'a';
            cur=++siz;
            s[cur].len =s[las].len+1;
            while(las!=0&&!s[las].ch[x])
                s[las].ch[x]=cur,las=s[las].par;
            if(las==0) s[cur].par=1;
            else{
                int q,nq;
                q=s[las].ch[x];
                if(s[q].len==s[las].len+1)
                    s[cur].par=q;
                else{
                    nq=++siz;
                    s[nq]=s[q],s[nq].len=s[las].len+1;
                    s[cur].par=s[q].par=nq;
                    while(las!=0&&s[las].ch[x]==q)
                        s[las].ch[x]=nq,las=s[las].par;
                }
            }
            las=cur;
        }
        const int LCS(string t){//求最长公共子串
            int le=0,ans=0;
            for(int i=0;t[i];i++){
                if(match(t[i])){
                    le++;
                    Transfer(le,t[i]);
                }
                else{
                    while(crp&&!s[crp].ch[t[i]-'a']) crp=s[crp].par;
                    if(crp==0) le=0,crp=1;
                    else le=s[crp].len+1,crp=s[crp].ch[t[i]-'a'];
                }
                ans=max(ans,le);
            }
            return ans;
        }
        LL getsub(){//求子串个数
            return dfs(1)-1;
        }
        LL dfs(int u){
            f[u]=1;
            for(int i=0;i<26;++i)
                if(s[u].ch[i]){
                    if(!f[s[u].ch[i]])
                        f[u]+=dfs(s[u].ch[i]);
                    else f[u]+=f[s[u].ch[i]];
                }
            return f[u];
        }
    }SAM;

     求字典序第k小子串

    https://www.luogu.org/problem/P3975

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define INF 0x3f3f3f3f
    #define LNF 0x3f3f3f3f3f3f3f3f
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define pqueue priority_queue
    #define NEW(a,b) memset(a,b,sizeof(a))
    #define rep(i, a, b) for(int i=(a); i<(b); i++)
    #define per(i, a, b) for(int i=(b)-1; i>=(a); i--)
    #define mem(a,x) memset(a,x,sizeof(a))
    const double pi=4.0*atan(1.0);
    const double e=exp(1.0);
    const int maxn=1e6+8;
    typedef long long LL;
    typedef long long ll;
    typedef unsigned long long ULL;
    const LL mod=1e9+7;
    const ULL base=1e7+7;
    const int maxp=26+5;
    using namespace std;
    int c[maxn],a[maxn],sum[maxn],si[maxn];
    struct Suffix_Node{
        int ch[maxp],par,len;
        void init(){
            NEW(ch,0);
            par=len=0;
        }
    };
    class Suffix_Automation{
    private:
        Suffix_Node s[maxn];
        int cur,las,siz,crp;
    public:
        Suffix_Automation():las(1),cur(1),siz(1),crp(1){}
        const void init(){
            for(int i=0;i<=siz;i++) s[i].init();
            las=cur=siz=crp=1;
        }
        const int match(const char c)const{
            return s[crp].ch[c-'a'];
        }
        const void withdraw(const int len){//撤掉开头几个字母,使已匹配的剩下长度为len
            while(crp!=0&&s[s[crp].par].len>=len) crp=s[crp].par;
            if(crp==0) crp=1;
        }
        const void Transfer(const int len,const char c){//匹配字符加上c保持长度为len
            crp=s[crp].ch[c-'a'];
            if(crp==0) crp=1;
            withdraw(len);
        }
        const void ex_tend(const char c){//扩展新字符
            int x=c-'a';
            cur=++siz;
            s[cur].len =s[las].len+1;
            si[cur]=1;
            while(las!=0&&!s[las].ch[x])
                s[las].ch[x]=cur,las=s[las].par;
            if(las==0) s[cur].par=1;
            else{
                int q,nq;
                q=s[las].ch[x];
                if(s[q].len==s[las].len+1)
                    s[cur].par=q;
                else{
                    nq=++siz;
                    s[nq]=s[q];
                    s[nq].len=s[las].len+1;
                    s[cur].par=s[q].par=nq;
                    while(las!=0&&s[las].ch[x]==q)
                        s[las].ch[x]=nq,las=s[las].par;
                }
            }
            las=cur;
        }
        const void print(int t,int k){//打印第k小子串,t为0表示不同位置的相同子串算作一个,t为1表示不同位置的相同子串算作多个
            for(int i=1;i<=siz;i++)
                c[s[i].len]++;
            for(int i=1;i<=siz;i++)
                c[i]+=c[i-1];
            for(int i=1;i<=siz;i++)
                a[c[s[i].len]--]=i;
            for(int i=siz;i;i--)
                if(t)
                    si[s[a[i]].par]+=si[a[i]];
                else
                    si[a[i]]=1;
            si[1]=0;
            for(int i=siz;i;i--){
                sum[a[i]]=si[a[i]];
                for (int j=0;j<26;j++)
                    if (s[a[i]].ch[j])
                        sum[a[i]]+=sum[s[a[i]].ch[j]];
            }
            if(k>sum[1]){
                puts("-1");
                return;
            }
            int now=1;
            k-=si[now];
            while(k>0){
                int p=0;
                while(k>sum[s[now].ch[p]]){
                    k-=sum[s[now].ch[p]];
                    p++;
                }
                now=s[now].ch[p];
                putchar('a'+p);
                k-=si[now];
            }
            return;
        }
    }SAM;
    char s[maxn];
    int main(){
        int t,k;
        scanf("%s%d%d",s,&t,&k);
        SAM.init();
        for(int i=0;s[i];i++){
            SAM.ex_tend(s[i]);
        }
        SAM.print(t,k);
    }

     求endpos集大小

    https://cn.vjudge.net/problem/HihoCoder-1465

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define INF 0x3f3f3f3f
    #define LNF 0x3f3f3f3f3f3f3f3f
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define pqueue priority_queue
    #define NEW(a,b) memset(a,b,sizeof(a))
    #define rep(i, a, b) for(int i=(a); i<(b); i++)
    #define per(i, a, b) for(int i=(b)-1; i>=(a); i--)
    #define mem(a,x) memset(a,x,sizeof(a))
    const double pi=4.0*atan(1.0);
    const double e=exp(1.0);
    const int maxn=2e6+8;
    typedef long long LL;
    typedef long long ll;
    typedef unsigned long long ULL;
    const LL mod=1e9+7;
    const ULL base=1e7+7;
    const int maxp=26+5;
    using namespace std;
    struct Suffix_Node{
        int ch[maxp],par,len;
        int w;//用于表示endpos集大小
        void init(){
            NEW(ch,0);
            par=len=0;
            w=0;
        }
    };
    struct node{
        int to,nxt;
    }g[maxn];
    int head[maxn],cnt;
    bool r[maxn];
    void add(int x,int y){
        g[cnt].to=y;
        g[cnt].nxt=head[x];
        head[x]=cnt++;
    }
    class Suffix_Automation{
    private:
        Suffix_Node s[maxn];
        int cur,las,siz,crp;
    public:
        Suffix_Automation():las(1),cur(1),siz(1),crp(1){}
        const void init(){
            for(int i=0;i<=siz;i++) s[i].init();
            las=cur=siz=crp=1;
        }
        const int match(const char c)const{
            return s[crp].ch[c-'a'];
        }
        const void withdraw(const int len){//撤掉开头几个字母,使已匹配的剩下长度为len
            while(crp!=0&&s[s[crp].par].len>=len) crp=s[crp].par;
            if(crp==0) crp=1;
        }
        const void Transfer(const int len,const char c){//匹配字符加上c保持长度为len
            crp=s[crp].ch[c-'a'];
            if(crp==0) crp=1;
            withdraw(len);
        }
        const void ex_tend(const char c){//扩展新字符
            int x=c-'a';
            cur=++siz;
            s[cur].len=s[las].len+1;
            s[cur].w=1;
            while(las!=0&&!s[las].ch[x])
                s[las].ch[x]=cur,las=s[las].par;
            if(las==0) {s[cur].par=1;}
            else{
                int q,nq;
                q=s[las].ch[x];
                if(s[q].len==s[las].len+1)
                    {s[cur].par=q;}
                else{
                    nq=++siz;
                    s[nq]=s[q];
                    s[nq].w=0;
                    s[nq].len=s[las].len+1;
                    s[cur].par=s[q].par=nq;
                    while(las!=0&&s[las].ch[x]==q)
                        s[las].ch[x]=nq,las=s[las].par;
                }
            }
            las=cur;
        }
        int gg(){
            return s[crp].w;
        }
        void dfs(int u){
            r[u]=1;
            for(int i=head[u];i!=-1;i=g[i].nxt){
                if(!r[g[i].to])
                    dfs(g[i].to);
                s[u].w+=s[g[i].to].w;
            }
        }
        void solve(){//求endpos集大小
            for(int i=1;i<=siz;i++){
                add(s[i].par,i);
            }
            for(int i=1;i<=siz;i++){
                if(!r[i]) dfs(i);
            }
        }
    }SAM,SAM2;
    char s[maxn],ss[maxn];
    bool vis[maxn];
    int main(){
        memset(head,-1,sizeof(head));
        scanf("%s",s);
        SAM.init();
        for(int i=0;s[i];i++){
            SAM.ex_tend(s[i]);
        }
        SAM.solve();
        int t,l;
        scanf("%d",&t);
        while(t--){
            SAM2.init();
            SAM.withdraw(0);
            scanf("%s",ss);
            l=strlen(ss);
            for(int i=l;i<2*l-1;i++){
                ss[i]=ss[i-l];
            }
            int ll=0;
            int ans=0;
            for(int i=0;i<2*l-1;i++){
                while(!SAM2.match(ss[i])){
                    ll--;
                    if(ll<0) break;
                    SAM2.withdraw(ll);
                }
                SAM2.ex_tend(ss[i]);
                SAM2.Transfer(++ll,ss[i]);
                if(ll>=l) vis[i]=1;
            }
            ll=0;
            for(int i=0;i<2*l-1;i++){
                while(!SAM.match(ss[i])){
                    ll++;
                    if(ll>i) break;
                    SAM.withdraw(i-ll);
                }
                SAM.Transfer(i-ll+1,ss[i]);
                if(i-ll+1>=l&&!vis[i]){
                    SAM.withdraw(l);
                    ll=i+1-l;
                    ans+=SAM.gg();
                }
            }
            for(int i=0;i<2*l-1;i++){
                vis[i]=0;
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    About Spring
    execle导入后 数据 无刷新 显示在 输入页面
    前端小神龟 -- 分页导航栏
    如何在mysql命令窗口获取到程序正在执行的sql语句
    div+css(ul li)实现图片上文字下列表布局
    C#异常之(已有打开的与此 Command 相关联,已有打开的与此命令相关联的 DataReader,必须首先将它关闭。)
    台灣VR內容產業聯盟_技術推廣中心
    2014新的一年到来,祝大家新年快乐
    matlab 提取文件路径名称,用于实现遍历读取文件(我的目的是遍历图像)
    无监督学习一些算法的简要概括(一)-稀疏自编码
  • 原文地址:https://www.cnblogs.com/Profish/p/11231000.html
Copyright © 2011-2022 走看看