kZjPBD.jpg

后缀自动机二·重复旋律5

时间限制:10000ms
单点时限:2000ms
内存限制:512MB

描述

小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。

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

解题方法提示

输入

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

输出

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

样例输入
aab
样例输出
5




SA可解,但是这次是学习SAM的解法
SAm建立的图中不会有一条路径是相同的字符串,所以所有字串的个数就是 每个状态的 manlen - minlen
而minlen 又等于 maxlen (fa[x])

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int last =1,tot=1;
 4 struct NODE 
 5 {
 6     int ch[26];
 7     int len,fa;
 8     NODE () {memset(ch,0,sizeof ch); len=fa=0;}
 9 
10 }dian[3000000];
11 
12 inline void add(int c)
13 {
14    int p = last; int np = last = ++tot; 
15   // cout<<c+'a'<<endl;
16    dian[np].len = dian[p].len+1;
17    for( ; p && !dian[p].ch[c]; p=dian[p].fa)dian[p].ch[c] = np;
18  //  cout<<" p: "<<p<<endl;
19    if(!p) dian[np].fa = 1;
20    else 
21    {
22     //   cout<<"HERE"<<endl;
23        int q=dian[p].ch[c];
24        if(dian[q].len == dian[p].len+1)dian[np].fa=q;
25        else
26        {
27            int nq=++tot;
28            dian[nq]=dian[q]; dian[nq].len=dian[p].len+1;
29            dian[q].fa=dian[np].fa=nq;
30            for(;p&&dian[p].ch[c]==q;p=dian[p].fa)dian[p].ch[c]=nq;
31        }
32    }
33 
34 
35 
36 }
37 int main()
38 {
39     string s;cin>>s; int len=s.length();
40     for (int i=0;i<len;i++)add(s[i]-'a');
41     long long ans = 0;
42     //cout<<tot<<endl;
43     for (int i=2;i<=tot;i++)ans+=dian[i].len - dian[dian[i].fa].len;
44     cout<<ans;
45 }

 







posted @ 2019-04-28 12:54  Through_The_Night  阅读(191)  评论(0)    收藏  举报