zoukankan      html  css  js  c++  java
  • spoj SUBST1

    SAM里的转台不会有重复串,所以答案就是每个right集合所代表的串个数的和

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=100005;
    int T,n,fa[N],ch[N][27],dis[N],cur=1,con=1,la;
    long long ans;
    char s[N];
    void ins(int c,int id)
    {
        la=cur,dis[cur=++con]=id;
        int p=la;
        for(;p&&!ch[p][c];p=fa[p])
            ch[p][c]=cur;
        if(!p)
            fa[cur]=1;
        else
        {
            int q=ch[p][c];
            if(dis[q]==dis[p]+1)
                fa[cur]=q;
            else
            {
                int nq=++con;
                dis[nq]=dis[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];
                fa[q]=fa[cur]=nq;
                for(;ch[p][c]==q;p=fa[p])
                    ch[p][c]=nq;
            }
        }
    }
    int main()
    {
    	scanf("%d",&T);
    	while(T--)
    	{
    		ans=0,con=1,cur=1;
    		memset(fa,0,sizeof(fa));
    		memset(ch,0,sizeof(ch));
    		scanf("%s",s+1);
    		n=strlen(s+1);
    		for(int i=1;i<=n;i++)
    			ins(s[i]-'a',i);
    		for(int i=1;i<=con;i++)
    			ans+=dis[i]-dis[fa[i]];
    		printf("%lld
    ",ans);
    	}
        return 0;
    }
    

    SA是对排序相邻的两个后缀减掉相同部分(height)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=100005;
    int T,n,wa[N],wb[N],wsu[N],wv[N],sa[N],rk[N],he[N];
    char s[N];
    long long ans;
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    bool cmp(int r[],int a,int b,int l)
    {
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void saa(char r[],int n,int m)
    {
        int *x=wa,*y=wb;
        for(int i=0;i<=m;i++)
            wsu[i]=0;
        for(int i=1;i<=n;i++)
            wsu[x[i]=r[i]]++;
        for(int i=1;i<=m;i++)
            wsu[i]+=wsu[i-1];
        for(int i=n;i>=1;i--)
            sa[wsu[x[i]]--]=i;
        for(int j=1,p=1;j<n&&p<n;j<<=1,m=p)
        {
            p=0;
            for(int i=n-j+1;i<=n;i++)
                y[++p]=i;
            for(int i=1;i<=n;i++)
                if(sa[i]>j)
                    y[++p]=sa[i]-j;
            for(int i=1;i<=n;i++)
                wv[i]=x[y[i]];
            for(int i=0;i<=m;i++)
                wsu[i]=0;
            for(int i=1;i<=n;i++)
                wsu[wv[i]]++;
            for(int i=1;i<=m;i++)
                wsu[i]+=wsu[i-1];
            for(int i=n;i>=1;i--)
                sa[wsu[wv[i]]--]=y[i];
            swap(x,y);
            p=1;
            x[sa[1]]=1;
            for(int i=2;i<=n;i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
        }
        for(int i=1;i<=n;i++)
            rk[sa[i]]=i;
        for(int i=1,j,k=0;i<=n;he[rk[i++]]=k)
            for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
    }
    int main()
    {
    	scanf("%d",&T);
        while(T--)
        {
    		ans=0;
    		scanf("%s",s+1);
    		n=strlen(s+1);
            saa(s,n,200);
    		for(int i=1;i<=n;i++)
    			ans+=n-sa[i]+1-he[i];
    		printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    第二次作业
    《自动化技术中的进给电气传动》读书笔记1.1-1.2
    证券投资分析
    微信官方文档概述
    联想拯救者Y7000电池无法充电问题
    Ubuntu用户权限管理
    证券市场基础知识
    Markdown All in One使用教程
    Markdown学习笔记
    第九周
  • 原文地址:https://www.cnblogs.com/lokiii/p/10008123.html
Copyright © 2011-2022 走看看