1. 程式人生 > >[BZOJ4516] [SDOI2016] 生成魔咒

[BZOJ4516] [SDOI2016] 生成魔咒

感覺還是SAM比較好寫QAQ。

顯然ans就是∑len[i]-len[fail[i]]

#include"bits/stdc++.h"
#define mmap map<int,int>::iterator
using namespace std;

const int N=200005;

struct SAM{
	map<int,int>e[N];long long res;
	int len[N],fail[N],cnt,last,n;
	SAM(){cnt=last=1;}
	int extend(int c){
		int p=last,np=++cnt;len[np]=len[p]+1;
		for(;e[p].find(c)==e[p].end()&&p;p=fail[p])
			e[p].insert(make_pair(c,np));
		if(!p)fail[np]=1;
		else {
			int q=e[p].find(c)->second,nq;
			if(len[q]==len[p]+1)fail[np]=q;
			else {
				nq=++cnt;len[nq]=len[p]+1;e[nq]=e[q];
				fail[nq]=fail[q],fail[q]=fail[np]=nq;
				for(mmap i;i=e[p].find(c),i->second==q;p=fail[p])
					i->second=nq;
			}
		}
		last=np;
		return len[np]-len[fail[np]];
	}
	void work(){
		scanf("%d",&n);int a,i;
		for(i=1;i<=n;i++){
			scanf("%d",&a);
			res+=extend(a);
			printf("%lld\n",res);
		}
	}
} sam;

int main(){
	sam.work();
	return 0;
}


相關推薦

bzoj4516: [Sdoi2016]生成

com OS stream cstring insert class pro code pri 傳送門 用阿伏伽德羅的話來說,典型的人類進化還不完全的時候的題。 一個裸的sam。 寫sam總是一不小心把np寫成p。。。 //Achen #include<algor

[BZOJ4516][SDOI2016]生成

turn print for == bzoj ++i += gpo com bzoj luogu 題意 求一個串每個前綴中含有多少個不同字串 \(n\le100000\),字符集大小\(10^9\) sol 後綴自動機的轉移開個\(map\)就好了。 每次插入以後,新增的貢

bzoj4516: [Sdoi2016]生成(SAM)

www. AD void long == map type oot online 4516: [Sdoi2016]生成魔咒 題目:傳送門 題解:    真奧義之SAM裸題...    其實對於當前新增節點x的操作,每次對ans的貢獻就是dep

BZOJ4516: [Sdoi2016]生成(字尾陣列 set RMQ)

題意 題目連結 Sol 毒瘤SDOI 終於有一道我會做的題啦qwq 首先,本質不同的子串的個數 $ = \frac{n(n + 1)}{2} - \sum height[i]$ 把原串翻轉過來,每次就相當於新增一個字尾 然後直接用set xjb維護一下前驅後繼就行了 時間複雜度:\(O(nlog

洛谷4070 BZOJ4516 SDOI2016 生成 SAM map

題目連結 題意: 你有 n n n次操作,每次往原串後面插入一個數,不同的數字看作不同的字元,問你每

[BZOJ4516] [SDOI2016] 生成

感覺還是SAM比較好寫QAQ。 顯然ans就是∑len[i]-len[fail[i]] #include"bits/stdc++.h" #define mmap map<int,int>:

[BZOJ4516][Sdoi2016]生成(字尾陣列+set/字尾自動機)

解法一:字尾陣列+set 國家集訓隊論文《字尾陣列——處理字串的有力工具 》中介紹過,長度為nn的字串不同的非空子串個數,等於 ∑i=1n(n−sa[i]+1−height[i])∑i=1n(n−sa[i]+1−height[i]) 由於∑ni=1sa[

[BZOJ4516][Sdoi2016]生成(字尾陣列+連結串列||字尾自動機)

題目描述 傳送門 題解 題意實際上是求對於每一個字首本質不同的子串個數 那麼可以轉化為對於每一個字首只求包含最後一個點的和前面不重複的子串個數,然後將答案累加 把串反過來建字尾陣列 然後

BZOJ4516: [Sdoi2016]生成-字尾陣列+線段樹+RMQ

傳送門 題意: 給出一個字串,分別求出前1~n位所含的不同的字串個數 n<=100000n<=100000 Solution: 看這道題的時候感覺到有後綴排序的那麼點意思,然而只是感覺到而已… 正解太TM神了 考慮對於一個字串,

[BZOJ4516][Sdoi2016]生成(字尾陣列+連結串列)

題目 傳送門 題解 這道題還是比較好的; 要求出每一個字首本質不同的字尾的個數,那麼我們可以把原序列倒過來,然後實際上就是對於每一個字尾求與其它字尾不重複的字首個數,也即是字尾長度減去height值; 求出某一個字尾對答案的貢獻之後,他不應該停留在

SDOI2016】【BZOJ4516生成

【題目連結】 【前置技能】 字尾樹 【題解】 要求支援向字串後加一個字元,詢問字串中本質不同的子串的個數。 考慮建立原串的反串的字尾樹,新出現的反串的字尾對於答案的貢獻為dep[pos]−dep[fa[pos]]dep[pos] - dep[fa[pos

bzoj 4516: [Sdoi2016]生成

++ 實現 struct ostream -s swa 一個 turn div Description 魔咒串由許多魔咒字符組成,魔咒字符可以用數字表示。例如可以將魔咒字符 1、2 拼湊起來形成一個魔咒串 [1,2]。 一個魔咒串 S 的非空字串被稱為魔咒串 S 的生成魔

●BZOJ 4516 [Sdoi2016]生成

ati tle mes http sin aps spa 代碼 需要 題鏈: http://www.lydsy.com/JudgeOnline/problem.php?id=4516 題解: 把串反過來後,問題變為求每個後綴的互不相同的子串個數。首先用倍增算法求出 sa[]

4516. [SDOI2016]生成【後綴自動機】

sdoi ace 字串 right 三種 esp oid n) 自動 Description 魔咒串由許多魔咒字符組成,魔咒字符可以用數字表示。例如可以將魔咒字符 1、2 拼湊起來形成一個魔咒串 [1,2]。 一個魔咒串 S 的非空字串被稱為魔咒串 S 的生成魔咒。

【文文殿下】 [SDOI2016]生成

字符集大小為1e9.............使用 map 吧 統計本質不同的子串個數是SAM的經典應用之一 本質不同的子串個數其實就是\(\sum max(x)-min(x)+1\) 所以我們新建結點 \(np\) 時統計它的答案即可 根據我們統計的式子,顯然新建節點\(nq\)的時候,不會對答案造成

BZOJ 4516: [Sdoi2016]生成(字尾陣列)

傳送門 解題思路   題目其實就是動態維護本質不同的串的個數。考慮到只有加數字的操作,所以可以用字尾陣列。題目是每次往後加數字,這樣不好處理,因為每次加數字之後所有的字尾都會改變。所以要轉化一下思路,就是將序列翻轉,這樣的話每次操作都是加入一個字尾,而對於一個串來說,本質不同的串的個數\(ans=\dfr

[Luogu P4070] [BZOJ 4516] [SDOI2016]生成

洛谷傳送門 題目描述 魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1,21,21,2 拼湊起來形成一個魔咒串 [1,2][1,2][1,2]。 一個魔咒串 SSS 的非空字串

luogu P4070 [SDOI2016]生成

首先有兩個結論: 1.字尾自動機具有最簡性,即每種不同的子串只會在sam上體現一次,體現形式是sam上一條由root出發的路徑。 2.一個字串不同子串的個數等於所有關鍵節點的max(x)-min(x)+1。證明就是考慮字尾自動機的最簡性。 然後,這就是個水題了。 每次插入一個字元後,更新答案即可。 #in

[洛谷P4070][SDOI2016]生成

題目大意:有一個字串,每次在末尾加入一個字元,問當前共有多少個本質不同的字串 題解:$SAM$,就是問插入這個字元後,多了多少個字串,就是當前這個點的$Right$陣列大小。 卡點:無   C++ Code: #include <cstdio> #include <

BZOJ 4516 [Sdoi2016] 生成

傳送門 心態崩了++ 字尾自動機板子題[考場上要是不會後綴自動機就崩了T^T] 可以看出 每次答案的貢獻就是和原來本質不同的子串數量 根據SPOJ7258我們可以得到 本質不同的子串數量可以通過建出自動機 樹形dp解決 我們需要知道的就是 連向它的那個鏈 就是我們建立自動