1. 程式人生 > >[SPOJ-DISUBSTR]Distinct Substrings

[SPOJ-DISUBSTR]Distinct Substrings

OS pri body namespace ast strlen http HR ++

vjudge

題意

給你一個串,求不同字串個數。
\(n\le10^5\)

sol

直接建SAM然後輸出\(\sum_{i=1}^{tot}len[i]-len[fa[i]]\)

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5+5;
int T,n,last=1,tot=1,tr[N][26],fa[N],len[N];
char s[N];long long ans;
void extend(int c)
{
    int
v=last,u=++tot;last=u; len[u]=len[v]+1; while (v&&!tr[v][c]) tr[v][c]=u,v=fa[v]; if (!v) fa[u]=1; else { int x=tr[v][c]; if (len[x]==len[v]+1) fa[u]=x; else { int y=++tot; memcpy(tr[y],tr[x],sizeof(tr[y])); fa[y]=fa[x];fa[x]=fa[u]=y;len[y]=len[v]+1
; while (v&&tr[v][c]==x) tr[v][c]=y,v=fa[v]; } } } int main() { scanf("%d",&T); while (T--) { scanf("%s",s+1);n=strlen(s+1); ans=0;last=tot=1; memset(tr,0,sizeof(tr)); memset(fa,0,sizeof(fa)); memset(len,0
,sizeof(len)); for (int i=1;i<=n;++i) extend(s[i]-'A'); for (int i=1;i<=tot;++i) ans+=len[i]-len[fa[i]]; printf("%lld\n",ans); } return 0; }

[SPOJ-DISUBSTR]Distinct Substrings