hihocoder1445 (后缀自动机)

1445 : 后缀自动机二·重复旋律5
时间限制:10000ms
单点时限:2000ms
内存限制:512MB
描述
小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。

现在小Hi想知道一部作品中出现了多少不同的旋律?

输入
共一行,包含一个由小写字母构成的字符串。字符串长度不超过 1000000。

输出
一行一个整数,表示答案。

样例输入
aab
样例输出
5


每个串只会被包含进一个状态
ans=cnti=1(max[i]min[i])=cnti=1(max[i]max[parent[i]]) a n s = ∑ i = 1 c n t ( m a x [ i ] − m i n [ i ] ) = ∑ i = 1 c n t ( m a x [ i ] − m a x [ p a r e n t [ i ] ] )

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back 
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
char s[1001000];
int tr[2001000][26] , par[2001000] , mx[2001000] , cnt , last , R[2001000];
ll ans;
int read()
{
    int sum = 0;char c = getchar();bool flag = true;
    while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
    while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
    if(flag)  return sum;
     else return -sum;
}  
void extand(int x)
{
    int np = ++cnt , p = last;R[np] = 1;
    mx[np] = mx[p] + 1;last = np;
    while(p && !tr[p][x]) tr[p][x] = np , p = par[p];
    if(!p) par[np] = 1;
    else
    {
        int q = tr[p][x];
        if(mx[q] == mx[p] + 1) par[np] = q;
        else
        {
            int nq = ++cnt;mx[nq] = mx[p] + 1;
            rep(i,0,25) tr[nq][i] = tr[q][i];
            par[nq] = par[q];par[q] = par[np] = nq;
            while(p && tr[p][x] == q) tr[p][x] = nq , p = par[p]; 
        }
    }
    return;
}
int main()
{
    scanf("%s",s+1);
    int len = strlen(s+1);cnt = last = 1;
    rep(i,1,len) extand(s[i]-'a');
    rep(i,1,cnt) ans += mx[i] - mx[par[i]];
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值