bzoj4516 SDOI2016 生成魔咒

2021-07-11 18:20:28 字數 1543 閱讀 3730

time limit: 10 sec  

memory limit: 128 mb

submit: 376  

solved: 232 [

submit][

status][

discuss]

魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1、2 拼湊起來形成乙個魔咒串 [1,2]。

乙個魔咒串 s 的非空字串被稱為魔咒串 s 的生成魔咒。

例如 s=[1,2,1] 時,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五種。s=[1,1,1] 時,它的生成魔咒有 [1]、

[1,1]、[1,1,1] 三種。最初 s 為空串。共進行 n 次操作,每次操作是在 s 的結尾加入乙個魔咒字元。每次操作後都

需要求出,當前的魔咒串 s 共有多少種生成魔咒。

第一行乙個整數 n。

第二行 n 個數,第 i 個數表示第 i 次操作加入的魔咒字元。

1≤n≤100000。,用來表示魔咒字元的數字 x 滿足 1≤x≤10^9

輸出 n 行,每行乙個數。第 i 行的數表示第 i 次操作後 s 的生成魔咒數量

71 2 3 3 3 1 213

691217

22鳴謝menci上傳

方法一:

字尾陣列

直接用字尾陣列比較難處理,因為每次加入新的元素後等於加入乙個字首,我們可以將整個字串翻轉,這樣就轉化成字尾了。

然後每加入乙個字尾,要求出新產生了多少個不同的子串。在height陣列中,找出前後相鄰的加入的字尾(樹狀陣列什麼的隨便搞搞就好),求出lcp的最大值,就是已經出現過的子串個數。用當前字尾的長度減去它就可以了。

#include#include#include#include#include#include#include#define f(i,j,n) for(int i=j;i<=n;i++)

#define d(i,j,n) for(int i=j;i>=n;i--)

#define ll long long

#define maxn 200005

#define inf 1000000000

using namespace std;

int n,cnt;

int a[maxn],b[maxn],c[maxn],x[maxn],y[maxn],sa[maxn],rnk[maxn],h[maxn],f[maxn][20],g[maxn][2];

ll ans;

mapmp;

inline int read()

while (ch>='0'&&ch<='9')

return x*f;

}inline void build_sa(int n,int m)

}inline void get_h()

}inline int rmq(int l,int r)

}

方法二:

字尾自動機

裸題直接將每個元素插入字尾自動機,然後ans+=mx[np]-mx[fa[np]]。

bzoj4516 Sdoi2016 生成魔咒

4516 sdoi2016 生成魔咒 time limit 10 sec memory limit 128 mb submit 575 solved 327 submit status discuss 魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1 2 拼湊起來形成乙個魔咒...

bzoj 4516 Sdoi2016 生成魔咒

time limit 10 sec memory limit 128 mb submit 1026 solved 576 submit status discuss 魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1 2 拼湊起來形成乙個魔咒串 1,2 乙個魔咒串 s 的非空字...

BZOJ4516 Sdoi2016 生成魔咒

bzoj4516 每次在結尾新增乙個數,相當於新增乙個字首。那麼倒過來看,變成每次在開頭新增乙個數,也就是新增乙個字尾。假若新的字尾長為 x 那麼相當於在原有的基礎上增加了 x個串,假設其中有 y 個串已經出現過。那麼a nsi ansi 1 x y考慮如何求這個y 考慮新加入的串和已有串的衝突。假...