字典樹 拓撲排序 第一!

2021-08-19 08:28:31 字數 1735 閱讀 4996

bessie一直在研究字串。她發現,通過改變字母表的順序,她可以按改變後的字母表來排列字串(字典序大小排列)。

例如,bessie發現,對於字串串「omm」,「moo」,「mom」和「ommnom」,她可以使用標準字母表使「mom」排在第乙個(即字典序最小),她也可以使用字母表「abcdefghijklonmpqrstuvwxyz」使得「omm」排在第乙個。然而,bessie想不出任何方法(改變字母表順序)使得「moo」或「ommnom」排在第乙個。

接下來讓我們通過重新排列字母表的順序來計算輸入中有哪些字串可以排在第乙個(即字典序最小),從而幫助bessie。

要計算字串x和字串y按照重新排列過的字母表順序來排列的順序,先找到它們第乙個不同的字母x[i]與y[i],按重排後的字母表順序比較,若x[i]比y[i]先,則x的字典序比y小,即x排在y前;若沒有不同的字母,則比較x與y長度,若x比y短,則x的字典序比y小,即x排在y前。

輸入格式

第1行:乙個數字n(1 <= n <= 30,000),bessie正在研究的字串的數量。

第2~n+1行:每行包含乙個非空字串。所有字串包含的字元總數不會超過300,000。 輸入中的所有字元都是小寫字母,即a~z。 輸入不包含重複的字串。

輸出格式

第1行:乙個數字k,表示按重排後的字母表順序排列的字串有多少可以排在第乙個數量。

第2~k+1行:第i+1行包含第i個按重排後的字母表順序排列後可以排在第乙個的字串。字串應該按照它們在輸入中的順序來輸出。

輸入輸出樣例

輸入樣例

4 omm

moo

mom

ommnom

輸出樣例

2 omm

mom

說明樣例即是題目描述中的例子,只有「omm」和「mom」在各自特定的字典序下可以被排列在第乙個。

首先容易想到當前串包含某個串的話,那麼肯定這個串不成立。

然後字元優先,等等,優先?怎麼很像拓撲排序?

於是想到相同字首的兩個字母連邊拓撲排序看看能不能跑完(即會不會形成環【衝突】)

相同字首什麼的肯定選擇字典樹啊(才不會kmp呢)

#include 

#include

#include

#include

#include

#define rep(i,a,b) for (i=a;i<=b;i++)

using

namespace

std;

int root=0,cnt;

int f[300001][26];

bool b[300001];

bool

map[26][26];

int rd[26];

string c[30001];

int n;

void inse(string a)

b[r]=1;

}void init()

}bool searchandget(int j)

r=f[r][x];

}return1;}

bool top()

}rep(i,0,25)

if (rd[i]) return

0; return1;}

void print()

printf("%d\n",k);

rep(i,1,n)

if (b[i])

cout

拓撲排序 字典序

1.用優先佇列維護 2.從後往前排序,每次判斷節點的出度,出度 0 進入優先佇列.3.用vector陣列做鄰接表表示整個圖 include include include include include using namespace std const int maxn 30005 vector ...

家譜樹(拓撲排序)

有個人的家族很大,輩分關係很混亂,請你幫整理一下這種關係。給出每個人的孩子的資訊。輸出乙個序列,使得每個人的後輩都比那個人後列出。第1行乙個整數n 1 n 100 表示家族的人數 接下來n行,第i行描述第i個人的兒子 每行最後是0表示描述完畢。輸出乙個序列,使得每個人的後輩都比那個人後列出 如果有多...

倍增字典序 拓撲排序 尋找數字

這裡介紹一種雜湊 倍增判斷字典序的方法,比較套路但不容易想到。設f x i f x i f x i 表示節點 x xx 往回跳 2 i2 i 2i所到達的點,w x i w x i w x i 表示節點 x xx 到 f x i f x i f x i 路徑中的最小值。那麼我們對於節點 u uu 和...