HDU 5769 Substring（后缀数组）

题意

$1 \leq |S| \leq 10^5$

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=1e5+5;
int sa[N],rk[N],H[N],tmp[3][N];
char s[N],str[N];
int nxt[N];
char X;
int n;

void get_SA(char *str,int n,int m)
{
int *x=tmp[0],*y=tmp[1],*c=tmp[2];
x[n+1]=y[n+1]=0;
FOR(i,1,m)c[i]=0;
FOR(i,1,n)c[x[i]=s[i]]++;
FOR(i,2,m)c[i]+=c[i-1];
DOR(i,n,1)sa[c[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
FOR(i,n-k+1,n)y[++p]=i;
FOR(i,1,n)if(sa[i]>k)y[++p]=sa[i]-k;
FOR(i,1,m)c[i]=0;
FOR(i,1,n)c[x[y[i]]]++;
FOR(i,2,m)c[i]+=c[i-1];
DOR(i,n,1)sa[c[x[y[i]]]--]=y[i];
std::swap(x,y);
p=x[sa[1]]=1;
FOR(i,2,n)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p;
if(n==p)break;
m=p;
}
FOR(i,1,n)rk[sa[i]]=i;
int k=0;
H[1]=0;
FOR(i,1,n)
{
if(k)k--;
if(rk[i]==1)continue;
int j=sa[rk[i]-1];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
H[rk[i]]=k;
}
}

ll query()
{
ll ans=0;
FOR(i,1,n)ans+=n-sa[i]+1-std::max(H[i],nxt[sa[i]]-sa[i]);
return ans;
}

int main()
{
int T;
scanf("%d",&T);
FOR(Ti,1,T)
{
scanf(" %c%s",&X,s+1);
n=strlen(s+1);
get_SA(s,n,256);
FOR(i,1,n)
{
if(s[i]==X)nxt[i]=i;
else nxt[i]=n+1;
}
DOR(i,n-1,1)chk_min(nxt[i],nxt[i+1]);
printf("Case #%d: %lld\n",Ti,query());
}
return 0;
}

posted @ 2019-03-22 22:21  Paulliant  阅读(47)  评论(0编辑  收藏