【題目描述】
由於你成功地在 $ \text $ 內算出了上一題的答案,英雄們很高興並邀請你加入了他們的遊戲。然而進入遊戲之後你才發現,英雄們打的遊戲和你想象的並不一樣……
英雄們打的遊戲是這樣的:首先系統會產生(**注意不一定是隨機產生**)乙個字串,然後每個英雄就會開始根據自己分到的任務計算這個字串的某些特徵,誰先算出自己的答案誰就是勝者。
由於打遊戲的英雄比較多,因此英雄們分到的任務也就可能很奇怪。比如你分到的這個任務就是這樣:
定義這個字串以第 $ i $ 個字元開頭的字尾為字尾 $ i $ (編號從 $ 1 $ 開始),每個字尾 $ i $ 都有乙個權值 $ w_i $ ,同時定義兩個字尾 $ i,j $ ($ i\ne j $) 的貢獻為它們的最長公共字首長度加上它們權值的異或和,也就是 $ \mathrm(i,j)+(w_i \mathbin} w_j) $ 。而你的任務就是,求出這個字串的所有字尾兩兩之間貢獻的最大值。
【輸入格式】
第一行乙個正整數 $ n $,表示字串的長度。
第二行乙個僅包含小寫英文本母的字串,即系統產生的字串。
第三行 $ n $ 個非負整數 $ w_i $,分別表示字尾 $ 1 $ ~ $ n $ 的權值。
【輸出格式】
一行乙個整數表示答案。
【樣例輸入】
7acbabac
0 1 5 6 4 2 3
【樣例輸出】
【樣例解釋】
字尾 $ 1 $ 和字尾 $ 4 $ 的貢獻是 $ 1+(0\;\text\;6)=7 $ ,不難驗證它們的貢獻確實是所有可能的貢獻中最大的。
【資料範圍與提示】
對於 $ 30\% $ 的資料,$ n\le 5\times 10^3 $;
對於另 $ 30\% $ 的資料,保證字串是隨機生成的;
對於另 $ 10\% $ 的資料,$ w_i=0 $;
對於另 $ 10\% $ 的資料,$ w_i\le 1 $;
對於 $ 100\% $ 的資料,$ n\le 10^5 $,$ w_i< n $ 。
求任意兩個字尾的 lcp 很容易想到字尾陣列
記排序後的兩個相鄰字尾 $ i-1,i $ 的 lcp 為 $ height[i] $
那麼任意的兩個字尾 $ i,j $ 的 lcp 為 $ min_^height[k] $
至於求 $w$ 的異或值考慮在 tire 樹上貪心
當 $ height[i] $ 為 $[l,r] $ 的最小值時才會對該區間有影響,那麼考慮如何用 $ height[i] $ 來更新答案
將 $ height[i] $ 從大到小排序後,合併 $ p_i $ 和 $ p_ $ 屬於的兩個區間 $ [l_,r_] $ 和 $ [l_},r_}] $,此時保證 $ height[i] $ 為兩個區間中的最小值(因為比 $ i $ 大的已經合併了)
然後在 tire 樹上啟發式合併兩個區間即可,貪心選取答案
時間效率:$ o(n \log n+n \log^2n)$
至於 sa 的排序可以用倍增法或者二分雜湊都可以(也就多乙個 $ \log $,反正啟發式合併也要 $ \log^2 $)
為什麼我一點都沒有感覺到套路,可能是題寫太少了
1 #include2view code#define ll long long
3#define _(d) while(d(isdigit(ch=getchar())))
4using
namespace
std;
5int
r()8
const
int n=2e5+5;9
intn,m,w[n],p[n],ht[n],rak[n],tp[n],sa[n],tax[n],ans;
10char
ch[n];
11void
qsort()
17void
sa()
29int k=0;30
for(int i=1,j;i<=n;i++)36}
37bool cmp(int a,int b)
38int li[n],ri[n],fa[n],rt[n],tot,tr[n*50][2
];39
int query(int k,int dep,int
val)
45void insert(int &k,int dep,int
val)
49int merge(int x,int
y)59
int find(int x)
60int
main()
字尾樹 字尾陣列
在字串處理當中,字尾樹和字尾陣列都是非常有力的工具,其中字尾樹大家了解得比較多,關於字尾陣列則很少見於國內的資料。其實字尾陣列是字尾樹的乙個非 常精巧的替代品,它比字尾樹容易程式設計實現,能夠實現字尾樹的很多功能而時間複雜度也不太遜色,並且,它比字尾樹所占用的空間小很多。可以說,在資訊學競賽 中字尾...
字尾樹 字尾陣列
我們考慮將乙個串的所有字尾插入乙個trie中,得到的trie就是字尾trie。我們可以發現,樹上有分叉或者是字尾節點的點的個數是o l en o len o len 個,這個後面解釋,於是把沒有分支並且不是字尾節點的點壓縮到一起,就變成了字尾樹。不難發現,字尾樹可以表示該字串的所有子串。下面分析一下...
字尾樹與字尾陣列
字尾樹和字尾陣列是字串處理的兩大神器,幾乎可處理掉一切的字串處理問題,但是在實際中,字尾陣列比字尾樹更好寫 好調,同時時間上也不差 常數很小 所以字尾陣列絕對是oi競賽之必備神器。字尾樹,實際上就是一棵字典樹。考慮將某個串 s 的所有字尾插到一棵trie裡,那麼我們就得到了一棵字尾樹。在這裡,我們不...