时间限制: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 }