魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 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 的生成魔咒數量
7 1 2 3 3 3 1 2
1 3
6 9
12 17
22資料約束:
對於 10% 的資料,1≤n≤10。
對於 30% 的資料,1≤n≤100。
對於 60% 的資料,1≤n≤1000。
對於 100% 的資料,1≤n≤100000。
用來表示魔咒字元的數字 x 滿足 1≤x≤109。
題解:
sam的裸題,但是打得字尾陣列,顯然是可以的,要求的是每個字首的子串數,顯然反轉一下就變成了字尾的子串數
imagine一下求平時子串個數的過程,l-lcp+1 lcp為i和i+1的high[i] 顯然這個題我們就可以類似的處理
加乙個字元反轉後就相當於加乙個字尾,我們考慮他的貢獻,顯然之和他rk的前驅後繼有關,於是我們減去原來的再加上現在的即可成為答案,前驅後繼set維護即可,或者玩玩splay treap也挺好
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include8using
namespace
std;
9const
int n=100005,inf=2e8;
10int n,sa[n],rk[n],high[n],c[n],x[n],b[n],bc[n],num=0
,s[n],y[n],bel[n];
11int
gi()
17int midit(int
x)25}26
intk;
27bool comp(int i,int
j)30
void
getsa()
51for(int i=1;i<=n;i++)rk[sa[i]]=i;52}
53void
gethight()61}
62long
long
ans[n];
63set
p;64int f[n][21
];65
void
prework()74}
75int query(int l,int
r)79
int lcp(int i,int
j)82
long
long
cnt[n];
83void
getanswer()
97 nxt=*(p.upper_bound(now));
98 cnt[now]=(n-sa[now]+1-lcp(now,nxt));
99 sum+=cnt[now];
100 ans[n-i+1]=sum;
101p.insert(now);
102}
103for(int i=1;i<=n;i++)printf("
%lld\n
",ans[i]);
104}
105int
main()
106
SDOI2016 生成魔咒
這是一道 sa 的練手好題 建議做之前先去做一下2408 之後你就肯定會做這道題了 首先上面那道題的答案就是 sum nn 1 sa i het i 就是對於每乙個字尾求出其能產生的子串,之後減掉和之前本質相同的子串 對於這個題,我們需要求出所有字首的本質不同的子串個數 先無腦敲上 sa 和 het...
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...
SDOI2016 生成魔咒(字尾自動機)
看一眼題。本質不同的字串數。嘴角微微上揚。每一次加乙個數輸出乙個答案。笑容漸漸消失。等等,sam 好像也可以求本質不同的字串。設當前字串用 x 表示,每次插入完成後 ans 加上 len x len fa 就行了。嘴角微微上揚。等等,炸空間了。笑容漸漸消失。用 map 不就得了。嘴角再次上揚。寫完過...