Ural 1590. Bacon’s Cipher 后缀数组

1590. Bacon’s Cipher

Time limit: 1.0 second
Memory limit: 64 MB
Programmer Vasya was down on his luck. Instead of a vacation, he was sent to a scientific conference.
“It is necessary to increase your competence,” his boss said, “it’s an important conference on cryptography, and it’s held in France, where they used encryption in the days of de Richelieu and cracked codes in the days of Viete.”
One of the talks at the conference was about the attempts to solve Bacon’s ciphers. The speaker proposed a hypothesis that the key to Bacon’s secrets could be found if all possible substrings of Bacon’s works were analyzed.
“But there are too many of them!” Vasya expressed his astonishment.
“Not as many as you think,” the speaker answered, “count them all and you’ll see it yourself.”
That evening Vasya found on the Web the complete set of Bacon’s works. He wrote a program that converted the texts into one long string by removing all linebreaks, spaces, and punctuation marks. And now Vasya is confused because he doesn’t know how to calculate the number of different substrings of this string.

Input

You are given a nonempty string consisting of lowercase English letters. The string is no longer than 5000 symbols.

Output

Output the number of different substrings of this string.

Sample

input output
aaba
8
Problem Author: Alex Gevak
Problem Source: ACM ICPC 2007–2008. NEERC. Eastern Subregion. Yekaterinburg, October 27, 2007
/** 2013_7_27
 *
 * Ural 1590. Bacon’s Cipher
 * 所有子串中不相同的个数
 * 后缀数组对后缀排序然后再进行后缀讨论
 * 倍增算法 r为待匹配数组  n为总长度 m为字符范围
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int const N = 5005;
int wa[N], wb[N], ws[N], wv[N];
int rank[N], sa[N], height[N], r[N], n, k;

int cmp( int* r, int a, int b, int L )
{
    return r[a]== r[b] && r[a+ L]== r[b+ L];
}

void da( int* r, int* sa, int n, int m )
{
    int i, j, p, *x= wa, *y= wb, *t;
    for( i= 0; i< m; ++i ) ws[i]= 0;
    for( i= 0; i< n; ++i ) ws[ x[i]= r[i] ]++;
    for( i= 1; i< m; ++i ) ws[i]+= ws[i-1];
    for( i= n- 1; i>= 0; i-- ) sa[ --ws[ x[i] ] ]= i;
    for( j= 1, p= 1; p< n; j*= 2, m= p )
    {
        for( p= 0, i= n- j; i< n; ++i ) y[p++]= i;
        for( i= 0; i< n; ++i )
            if( sa[i]>= j ) y[p++]= sa[i]- j;
        for( i= 0; i< n; ++i ) wv[i]= x[y[i]];
        for( i= 0; i< m; ++i ) ws[i]= 0;
        for( i= 0; i< n; ++i ) ws[ wv[i] ]++;
        for( i= 1; i< m; ++i ) ws[i]+= ws[i-1];
        for( i= n- 1; i>= 0; i-- ) sa[ --ws[ wv[i] ] ]= y[i];
        t= x, x= y, y= t, p= 1;
        x[ sa[0] ]= 0;
        for( i= 1; i< n; ++i )
            x[ sa[i] ]= cmp( y, sa[i-1], sa[i], j )? p- 1: p++;
    }
}
void callheight( int* r, int*sa, int n )
{
    int i, j, k= 0;
    for( i= 1; i<= n; ++i ) rank[ sa[i] ]= i;
    for( i= 0; i< n; height[ rank[i++] ]= k )
        for( k?k--:0, j= sa[ rank[i]- 1]; r[i+k]== r[j+k]; k++ );
}
char s[5005];
int main()
{
    int i, ans;
    scanf("%s", s);
    n = strlen(s);
    for(i = 0; i < n; i ++) r[i] = (int)s[i];
    da(r, sa, n + 1, 265);
    callheight( r, sa, n );
    ans = n*(n+1)/2;
    for(i = 1; i <= n; i ++) ans -= height[i];
    printf("%d\n", ans);
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值