SCOI2016 背單詞 題解

2021-09-10 19:19:17 字數 2521 閱讀 7546

題意的話就看題面吧。

我們一步一步的來分析:

首先吃最少的泡椒,那麼顯然可以貪心,由於n×n

n\times n

n×n貢獻的肯定比後面的方式都大,所以我們考慮將乙個串它的所有存在的字尾串全部先放在前面,這時就不會用第一種了,然後我們考慮,可以將這種關係用邊連起來,就成了一棵樹,我們可以舉個例子來看:

5ab

babb

bba

這個例子便可以連出這樣的一張圖:

我們發現,如果先放a

aa這邊的,那麼最後就會是:

a - 1

ba - 1

bba - 1

b - 4

bb - 1

cost = 8

但是我們明顯可以發現如果先放b

bb這邊的,那麼當到a

aa時,它只會有3

33的代價,而其他都是1

11的代價,所以如下這樣會更優秀:

b - 1

bb - 1

a - 3

ba - 1

bba - 1

cost = 7

那麼貪心的考慮,也就是這棵樹上,我們按照子樹大小,從小到大的遍歷會更優秀一些。

所以一種方法是用hash演算法,在o(n

2)o(n^2)

o(n2

)的時間內建出這個樹,然後遍歷一遍排個序就可以出答案了。

目前瓶頸就在於建樹,我們可以發現它的每個都是和字尾有關,但是直接建一棵廣義字尾自動機太麻煩了,所以我們將其翻轉後,字尾就變成了字首,那麼只需插入到一棵trie(字典)樹中即可,對於乙個串是另乙個串的字首,那麼在字典樹上它就是另乙個的祖先(在另乙個同一條鏈的上面),然後遍歷一遍即可建出原樹。

複雜度變成o(∣

len∣

∗26+n

)o(|len|*26+n)

o(∣len

∣∗26

+n)就可以過了。

**:

#include

#include

#include

#include

#define ll long long

using

namespace std;

const

int n=

1e5+

5,m=

6e5+1;

int n,bef[n]

;char str[m]

;ll ans;

int son[m][26

],f[n]

,flag[m]

,sze[n]

,bel[m]

,tot=1;

struct ssss(

int a,

int b):to

(a),

last

(b)}g[m]

;int head[n]

,cnt;

void

add(

int a,

int b)

void

addin

(char

*s,int k)

bel[now]

=k;//建trie樹,記錄是哪個字串

}struct node

node

(int a,

int b)

:sze

(a),

id(b)

bool

operator

<

(node a)

const

//按子樹大小排序};

vector vec[n]

;void

dfs(

int a,

int fa)

//建樹

}void

find

(int a)

sort

(vec[a]

.begin()

,vec[a]

.end()

);//排序

}int rak;

void

get(

int a)

void

file()

void

close()

intmain()

dfs(1,

0);find(0

);get(0)

;for

(int i=

1;i<=n;i++

) ans+

=1ll

*(bef[i]

-bef[f[i]])

;//統計答案

printf

("%lld\n"

,ans)

;close()

;return0;

}

Scoi2016 背單詞(trie 貪心)

題意 重新解釋一下題意吧 題意晦澀難懂 給定n個單詞,你可以按照順序學習,當學習這一單詞時,這個單詞是第x個要學習的單詞,需要的代價分三類 1 若存在其他單詞是其字尾沒被學習,則代價為n2 2 若不存在其他單詞是其字尾,則代價是x 3 否則代價是x y y是最靠後的是其字尾的單詞學習的位置 題解 首...

SCOI2016 背單詞 Trie樹,貪心

題目鏈結 首先吐槽一波原題意,描述地太不清楚了,還是出題人想要出語文斷句題?題目鏈結是團隊考試的題,題意重置版。顯然我們要避免那種 i i 的情況,因為這樣非常不划算,i 2 i i j 那我們來看看能不能安排乙個合法的順序來規避這個情況。顯然是可以的,因為如果我們按照字尾關係連邊,它會形成乙個 d...

洛谷P3294 SCOI2016 背單詞 題解

題目傳送 閱讀理解題題意解釋可以看這位大佬的部落格。發現求字尾與倒序求字首是等價的,而找字首自然就想到了trie樹。將所有字串翻轉後再建入trie樹中,再對每乙個字串翻轉後從trie樹中找字首,就能找到乙個字串的所有字尾了。由第三種情況知我們要想最小化總代價,則最小化乙個字串與最靠近它的字尾間的距離...