HYSBZ 弦論(字尾自動機)

2021-10-04 14:00:57 字數 1602 閱讀 1561

description

對於乙個給定長度為n的字串,求它的第k小子串是什麼。

input

第一行是乙個僅由小寫英文本母構成的字串s

第二行為兩個整數t和k,t為0則表示不同位置的相同子串算作乙個。t=1則表示不同位置的相同子串算作多個。k的意義如題所述。

output

輸出僅一行,為乙個數字串,為第k小的子串。如果子串數目不足k個,則輸出-1

sample input

aabc 0 3

sample output

aabhint

n<=5*10^5

t<2

k<=10^9

題意:沒什麼好解釋的。

解法:利用字尾自動機,開陣列cnt儲存當前結點包含的字串個數,sum儲存後繼結點包含的字串個數(相當於以此為字首的字串個數),拓撲排序求出endpos,對於t=1,不同位置的相同子串算兩個,此時cnt就是當前結點的endpos個數,對於t=0,不同位置的相同子串算乙個,此時cnt就是1。注意源點(也就是1)的cnt和sum在計算結束後要重新賦值為0,因為源點是空的。

處理完畢後從源點進行dfs,按順序遍歷所有的26個分支(相當於字典序),對於存在的分支,如果它之後的字元個數比k小,說明還沒有到第k小的子串,從k中減去字串個數(相當於去掉了這麼多個子串),繼續遍歷下乙個分支,如果大於等於k,說明該分支已經到了第k小的子串,輸出對應的字母,減去該字母對應的字串個數,如果k依然大於0,意味著還沒到第k小的子串,對該分支進行dfs,遍歷結束(當前分支已經滿了k個,不需要遍歷其他分支了)。

好了我承認,其實我就是在對著大佬的**腦補。

大佬的**:

**:

#include

#include

#include

#include

#include

using

namespace std;

const

int n=

1e6+10;

struct nodedian[n]

;int k,t,lens,las=

1,tot=1;

int a[n]

,b[n]

,sum[n]

,cnt[n]

;char s[n]

;int

add(

int c)

} cnt[np]=1

;}void

dfs(

int u,

int k)}}

intmain()

sum[1]

=cnt[1]

=0;for

(int i=tot;i>=

1;i--)}

if(k>sum[1]

)printf

("-1\n");

else

dfs(

1,k)

,printf

("\n");

return0;

}

BZOJ3998 弦論 字尾自動機

題意 給定乙個長度為n的字串,求他的第k小子串是什麼。分析t 0的時候,這個題跟spoj sublex的做法一樣,當t 1的時候,不同位置的子串算多個,那麼初始化的時候d u cnt u 沒走乙個字元不是k 1而是k cnt u 1 include 2 include 3 include 4 inc...

bzoj3998 弦論 字尾自動機

對於乙個給定長度為n的字串,求它的第k小子串是什麼。第一行是乙個僅由小寫英文本母構成的字串s 第二行為兩個整數t和k,t為0則表示不同位置的相同子串算作乙個。t 1則表示不同位置的相同子串算作多個。k的意義如題所述。輸出僅一行,為乙個數字串,為第k小的子串。如果子串數目不足k個,則輸出 1 aabc...

3998 TJOI2015 弦論 字尾自動機

description 對於乙個給定長度為n的字串,求它的第k小子串是什麼。這道題感覺真的很入門啊 建出字尾自動機,對於t 0 t 0 預設所有節點的ri ght rig ht 集合為1,對於t 1 t 1 就直接正常求出ri ght rig ht 集合,然後對每個點求個su m x s um x ...