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 ...