SPOJ Distinct Substrings SA

正解:SA

解题报告:

传送门!

啊先给个翻译趴QwQ大概就是说给个字符串,求互不相等的子串的个数

算是道小水题辣趴,,,并不难想到的呢QAQ只是因为是新知识所以巩固下而已QAQ

然后就显然考虑合法方案就会是所有方案-不合法方案

所有方案显然是n*(n+1)/2,不合法方案就是相等的子串的个数

考虑相等的子串的个数怎么求?不就是,∑height[i]

欧克做完了

 

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)

const int N=60000+10;
int x[N],y[N],sa[N],rk[N],t[N],n,as;
char ch[N];

il int read()
{
    rc ch=gc;ri x=0;rb y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il bool cmp(ri gd,ri gs,ri k){return y[gd]==y[gs] && y[gd+k]==y[gs+k];}
il void SA()
{
    ri m=50000,h=0;
    rp(i,1,n)++t[x[i]=ch[i]-'A'+1];
    rp(i,1,m)t[i]+=t[i-1];
    my(i,n,1)sa[t[x[i]]--]=i;
    for(ri k=1;k<=n;k<<=1)
    {
        ri p=0;
        rp(i,1,n)y[i]=0;rp(i,0,m)t[i]=0;
        rp(i,n-k+1,n)y[++p]=i;rp(i,1,n)if(sa[i]>k)y[++p]=sa[i]-k;
        rp(i,1,n)++t[x[y[i]]];
        rp(i,1,m)t[i]+=t[i-1];
        my(i,n,1)sa[t[x[y[i]]]--]=y[i];
        swap(x,y);
        x[sa[1]]=p=1;
        rp(i,2,n)x[sa[i]]=cmp(sa[i],sa[i-1],k)?p:++p;
        if(p>=n)break;m=p;
    }
    rp(i,1,n)rk[sa[i]]=i;
    rp(i,1,n)
    {
        if(h)--h;
        while(ch[i+h]==ch[sa[rk[i]-1]+h])++h;
        as-=h;
    }
}

int main()
{
    ri T=read();
    while(T--)
    {
        memset(x,0,sizeof(x));memset(y,0,sizeof(y));memset(t,0,sizeof(t));memset(sa,0,sizeof(sa));memset(rk,0,sizeof(rk));
        scanf("%s",ch+1);n=strlen(ch+1);as=n*(n+1)/2;SA();printf("%d\n",as);
    }
    return 0;
}
这儿是代码QwQ

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/10657880.html