1. 程式人生 > >字尾自動機 【Sdoi2016】生成魔咒 bzoj4516

字尾自動機 【Sdoi2016】生成魔咒 bzoj4516

題目大意:
給你n個數,每個數代表一個不同的字元。
初始為空串,每次在裡面插入一個字元,並且詢問本質不同的子串的個數。

題目分析:(字尾自動機)
字尾自動機想要表示所有的字尾以及字尾的字首,就會有性質:min_len=fa->max _len+1。
並且max_len-min _len+1就代表當前節點所表示的本質不同的子串的個數。
(這些字尾自動機的性質還需要我們感性的理解啊……)
所以我們在每次插入的時候維護一下更改節點的max_len值,並且把答案加上max _len- fa->max _len,輸出答案就可以了。

注意事項:
1、因為q的father改變了,所以先給他的max_len減掉,再在後面給它加回來;
2、因為你並不知道一共有多少個字元,所以用map存兒子;
3、答案用long long輸出。

程式碼如下:

#include<cstdio>
#include<map>
using namespace std;
int n;
long long ans;
struct SAM{
    map<int,SAM*> son;
    SAM *fa;
    int max_len;
    SAM(int _=0):fa(NULL),max_len(_){}
}*root=new SAM,*last=root;
void extend(int x)
{
    SAM *p=last;
    SAM *np=new SAM(p->max_len+1
); while(p && !p->son[x]) p->son[x]=np,p=p->fa; if(!p) np->fa=root; else { SAM *q=p->son[x]; if(p->max_len+1==q->max_len) np->fa=q; else { SAM *nq=new SAM(p->max_len+1); ans-=q->max_len-q->fa->max_len; nq->fa=q->fa; nq->son=q->son; q->fa=nq;np->fa=nq; for
(;p && p->son[x]==q;p=p->fa) p->son[x]=nq; ans+=q->max_len-q->fa->max_len; ans+=nq->max_len-nq->fa->max_len; } } last=np; ans+=np->max_len-np->fa->max_len; } int main() { scanf("%d",&n); for(int i=1,x;i<=n;i++) { scanf("%d",&x); extend(x); printf("%lld\n",ans); } return 0; }

相關推薦

字尾自動機 Sdoi2016生成 bzoj4516

題目大意: 給你n個數,每個數代表一個不同的字元。 初始為空串,每次在裡面插入一個字元,並且詢問本質不同的子串的個數。 題目分析:(字尾自動機) 字尾自動機想要表示所有的字尾以及字尾的字首,就會

bzoj4516SDOI2016生成

4516: [Sdoi2016]生成魔咒 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 376  Solved: 232 [Submit][Sta

BZOJ4516SDOI2016生成(SAM)

Description 魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1、2 拼湊起來形成一個魔咒串 [1,2]。 一個魔咒串 S 的非空字串被稱為魔咒串 S 的生成魔咒。

BZOJ4516生成字尾自動機

題面 BZOJ Description 魔咒串由許多魔咒字元組成,魔咒字元可以用數字表示。例如可以將魔咒字元 1、2 拼湊起來形成一個魔咒串 [1,2]。 一個魔咒串 S 的非空字串被稱為魔咒串 S 的生成魔咒。 例如 S=[1,2,1] 時,它的

SDOI2016BZOJ4516生成

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

LibreOJ #2033. 「SDOI2016生成

col clas uil str stat swap pri pre evel 二次聯通門 : LibreOJ #2033. 「SDOI2016」生成魔咒 /* LibreOJ #2033. 「SDOI2016」生成魔咒 調了整整一天啊

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\)的時候,不會對答案造成

[SDOI2016]生成

ans char oid -h 排名 new ring 動態 答案 這是一道\(SA\)的練手好題 建議做之前先去做一下2408 之後你就肯定會做這道題了 首先上面那道題的答案就是 \[\sum_{i=1}^nn+1-sa[i]-het[i]\] 就是對於每一個後綴求出其能

[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]生成字尾陣列+連結串列||字尾自動機

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

BZOJ 4516: [Sdoi2016]生成 字尾自動機

4516: [Sdoi2016]生成魔咒 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1328  Solved: 745 [Submit][St

SDOI2016bzoj4516 生成解法一

每次在SAM中加入一個字元,維護每個點的vali−valfaili即可。 因為字符集很大,離散化以後也開不下,可以用map存轉移。 #include<cstdio> #include&l

LG4070[SDOI2016]生成

構建 char break oid www. www org tchar ans 【LG4070】[SDOI2016]生成魔咒 題面 洛谷 題解 如果我們不用在線輸的話,那麽答案就是對於所有狀態\(i\) \[ \sum (i.len-i.fa.len) \] 現在我們需要

洛谷4070 [SDOI2016]生成(SAM)

show 就是 代碼實現 sum 在線 字符串 什麽 pcs problem 傳送門 洛谷 Solution 考慮要求的是什麽,前綴的本質不同的字符串個數? 如果只要求一個串那麽顯然答案是\(\sum_{i=1}^{tot}len[i]-len[fa[i]]\)(實際上這個

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

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

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

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

BZOJ[4516][Sdoi2016]生成 字尾陣列+ST表+線段樹

首先感謝Sinogi大佬的耐心講解及程式碼 題意就是每次加一個字元,統計本質不同的子串數量 正向新增字元不好做,考慮反著刪字元 在正常情況下,刪掉位置ii的一個字元會減少ii個子串(∑j<=ij=1sj...i∑j=1j<=isj...i)

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

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

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

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