生活随笔
收集整理的這篇文章主要介紹了
hihoCoder #1445 : 后缀自动机二·重复旋律5
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
描述
小Hi平時的一大興趣愛好就是演奏鋼琴。我們知道一個音樂旋律被表示為一段數構成的數列。
現在小Hi想知道一部作品中出現了多少不同的旋律?
輸入
共一行,包含一個由小寫字母構成的字符串。字符串長度不超過 1000000。
輸出
一行一個整數,表示答案。
樣例輸入
aab
樣例輸出
5
思路
后綴自動機板子
子串的種類數 = ∑maxlen?minlen{ \sum maxlen - minlen}∑maxlen?minlen,每種狀態表示一個長度的范圍的子串,求sum即可
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i <= n; ++i)
const int maxn
= 1e6+6;
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
using namespace std
;
struct SAM
{int trans
[maxn
<<1][26], slink
[maxn
<<1], maxlen
[maxn
<<1];int last
, now
, root
;void newnode
(int v
) {maxlen
[++now
] = v
;}void extend(int c
) {newnode(maxlen
[last
] + 1);int p
= last
, np
= now
;while (p
&& !trans
[p
][c
]) {trans
[p
][c
] = np
;p
= slink
[p
];}if (!p
) slink
[np
] = root
;else {int q
= trans
[p
][c
];if (maxlen
[p
] + 1 != maxlen
[q
]) {newnode(maxlen
[p
] + 1);int nq
= now
;memcpy(trans
[nq
], trans
[q
], sizeof(trans
[q
]));slink
[nq
] = slink
[q
];slink
[q
] = slink
[np
] = nq
;while (p
&& trans
[p
][c
] == q
) {trans
[p
][c
] = nq
;p
= slink
[p
];} }else slink
[np
] = q
;}last
= np
;}void build(string s
) {root
= last
= now
= 1;mem(trans
, 0);mem(slink
, 0);mem(maxlen
, 0);int len
= s
.size();for (int i
= 0; i
< len
; ++i
) extend(s
[i
] - 'a');}LL all
() {LL ans
= 0;for (int i
= root
+1; i
<= now
; ++i
) {ans
+= maxlen
[i
] - maxlen
[ slink
[i
] ];}return ans
;}
}sam
;int main() {
#ifndef ONLINE_JUDGE
#endifios
::sync_with_stdio(false);cin
.tie(0); cout
.tie(0);string s
;cin
>> s
;sam
.build(s
);cout
<< sam
.all() << endl
;return 0;
}
總結
以上是生活随笔為你收集整理的hihoCoder #1445 : 后缀自动机二·重复旋律5的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。