link
一開始給乙個空串 s
ss,每次在其最後加入乙個字元 x
xx,詢問每次加入後 s
ss 的本質不同的非空子串的個數。
∣ s∣
≤105
,1≤x
≤109
.|s|\le 10^5, 1\le x\le 10^9.
∣s∣≤10
5,1≤
x≤10
9.具體地說,加入乙個字元 x
xx 得到的貢獻就為 len
(np)
−len
(fa(
np))
len(np)-len(fa(np))
len(np
)−le
n(fa
(np)
)。那麼這題就做完了。
#include
#include
#include
#include
using
namespace std;
typedef
long
long ll;
char in[
1<<20]
,*ss = in,
*tt = in;
#define getchar() (ss == tt && (tt = (ss = in) + fread(in, 1, 1 << 20, stdin), ss == tt) ? eof : *ss++)
ll read()
const
int maxn =
2e5+5;
int n, lst =
1, tot =1;
ll ans;
struct nodee[maxn]
;void
ins(
int c)}}
intmain()
return0;
}
我們每次加入乙個字元,所有的字尾都會發生變化。於是我們不妨倒轉這個串,改為在之前新增字元,這樣每次就只增加乙個字尾。
不妨把新增變成刪除,考慮每次刪除頭乙個字元的貢獻。不難發現,貢獻為 n−i
+1
−max
n-i+1-\max\(\mathrm(i)),\mathrm(\mathrm(i+1))\}
n−i+1−
max。然後再刪去這個位置,更新 hei
gh
t\mathrm
height
即可。這個操作可以用乙個鍊錶簡單地完成。
#include
#include
#include
using
namespace std;
typedef
long
long ll;
char in[
1<<20]
,*ss = in,
*tt = in;
#define getchar() (ss == tt && (tt = (ss = in) + fread(in, 1, 1 << 20, stdin), ss == tt) ? eof : *ss++)
ll read()
const
int maxn =
2e5+5;
int n;
int s[maxn]
, lsh[maxn]
, lsh_num, sa[maxn]
, rk[maxn]
, ht[maxn]
, x[maxn]
, y[maxn]
, c[maxn]
, nxt[maxn]
, pre[maxn]
;ll ans[maxn]
;void
suffixsort()
}void
getheight()
int j = sa[rk[i]-1
];while
(i+k <= n && j+k <= n && s[i+k]
== s[j+k]
) k++
; ht[rk[i]
]= k;}}
intmain()
for(
int i = n; i >=
1; i--
) ans[i]
+= ans[i+1]
;for
(int i = n; i >=
1; i--
)printf
("%lld\n"
, ans[i]);
return0;
}
P4070 SDOI2016 生成魔咒
魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 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...
P4070 SDOI2016 生成魔咒(SAM)
題意 一開始有乙個空陣列,n次操作,每次操作都是在陣列的末尾追加乙個數x,要求操作之後輸出陣列中本質不同的子陣列數量。資料範圍 n 1e5,1 x 1e9 解法 本質不同子串容易想到sam,本質不同的子串數量 sum l i l fa i 每次插入乙個新數的時候,設新節點為np,那麼答案累加l np...
LG4070 SDOI2016 生成魔咒
洛谷 sum i.len i.fa.len 那麼產生的貢獻就是 last.len last.fa.len 與 yyb 的對話 q 為什麼構建自動機時中間過程新加的點不會算到最後答案中呢?a 不影響答案啊,你在兩個len之間斷開,對於答案的貢獻不變。include include include in...