3238: [Ahoi2013]差异
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3443 Solved: 1562
[ Submit][ Status][ Discuss]
Description
Input
一行,一个字符串S
Output
一行,一个整数,表示所求值
Sample Input
cacao
Sample Output
54
后缀数组height数组有个很好的性质:
Lcp(i, j) = min(height[k], k∈[i+1, j] )
这样在算∑lcp(i, j)时,就可以用单调栈计算每个最小值的贡献了
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL long long
typedef struct
{
int l;
int r;
}Point;
Point s[500010];
char str[500010];
int q, n, st[500010], a[500010], Rank[500010], Temp[500010], cot[500050], Sa[500010], height[500010];
int main(void)
{
LL ans;
int i, m, p, k, top;
scanf("%s", str+1);
n = strlen(str+1);
for(i=1;i<=n;i++)
a[i] = str[i];
m = 128;
for(i=1;i<=n;i++)
{
Rank[i] = a[i];
cot[a[i]]++;
}
for(i=1;i<=m;i++)
cot[i] += cot[i-1];
for(i=n;i>=1;i--)
Sa[cot[a[i]]--] = i;
for(k=1;k<=n;k*=2)
{
p = 0;
for(i=n-k+1;i<=n;i++)
Temp[++p] = i;
for(i=1;i<=n;i++)
{
if(Sa[i]>k)
Temp[++p] = Sa[i]-k;
}
memset(cot, 0, sizeof(cot));
for(i=1;i<=n;i++)
cot[Rank[i]]++;
for(i=1;i<=m;i++)
cot[i] += cot[i-1];
for(i=n;i>=1;i--)
Sa[cot[Rank[Temp[i]]]--] = Temp[i];
swap(Rank, Temp);
p = 1;
Rank[Sa[1]] = 1;
for(i=2;i<=n;i++)
{
if(Temp[Sa[i-1]]==Temp[Sa[i]] && Temp[Sa[i-1]+k]==Temp[Sa[i]+k])
Rank[Sa[i]] = p;
else
Rank[Sa[i]] = ++p;
}
m = p;
}
k = 0;
for(i=1;i<=n;i++)
{
k = max(k-1, 0);
m = Sa[Rank[i]-1];
while(a[i+k]==a[m+k])
k++;
height[Rank[i]] = k;
}
ans = 0;
for(i=n;i>=1;i--)
ans += (LL)i*(n-1);
top = 0;
for(i=1;i<=n;i++)
{
while(top>=1 && height[st[top]]>=height[i])
{
s[st[top]].r = i-1;
top--;
}
s[i].l = st[top];
st[++top] = i;
}
while(top)
{
s[st[top]].r = n;
top--;
}
for(i=1;i<=n;i++)
ans -= (LL)2*(s[i].r-i+1)*(i-s[i].l)*height[i];
printf("%lld\n", ans);
return 0;
}
/*
aaaaaa
*/