求不重複子串數

2021-10-04 19:43:14 字數 3525 閱讀 1469

試題 演算法提高 著急的wyf(不同子串個數)

提交此題

資源限制

時間限制:476ms 記憶體限制:256.0mb

問題描述

由於戰網的密碼是一串亂碼,wyf巧妙地忘記了他的密碼。(他就是作死,如同自掘墳墓。說到掘墳墓,問題就來了——挖掘機技術究竟哪家強?)他現在非常著急,走投無路,都快飛起來了。他只記得他的密碼是某個字串s的子串。現在問題來了,你要告訴他有多少種可能的密碼,以幫助他確定他能在多少時間內完成列舉並嘗試密碼的工作。

輸入格式

輸入僅包含一行,為字串s,不含空格。

輸出格式

輸出乙個整數,表示可能的密碼數量。

樣例輸入

total

樣例輸出

14資料規模和約定

對於70%的資料,s的長度不超過1000;(暴力)

對於100%的資料,s的長度不超過15000。(suffix array)

推薦擁有字尾陣列桶排法技能的人進行**!!開個玩笑,本題解法使用了字尾陣列的改裝,所以需要對字尾陣列有一定的了解。講字尾陣列的網上有很多,而且我覺得已經寫得很好了,這裡就不過多的進行闡述了。

這題目乍一看好難下手,暴力求解妥妥的超時。那我們把這個題目,大題化小,小題化了…

依次計算出,長度為1,2,3,…的子串不重複數。比如:計算長度為4的子串數,此時已知長度為3的子串rank排名,把長度3子串左邊乙個字元當『十位』,長度3子串當『個位』,桶排一下。最後比較一下相鄰排名是不是重複的就行了。

ps.看懂了這段的就直接跳到**吧(表達的不是很好,估計都看不懂吧)。

首先,把不同長度的子串拆開了算,最後加一起就行了。這樣,我們考慮的就是一堆長度固定的字串,求不重複的有幾個。

嗯,還是挺麻煩的,開個掛先:假如我把第一步的字串從大到小標記好了(按字典序標記,最小的標記為1,重複的標記數字相同),但是我又在每個子串的前面加了乙個隨機的字元,問:現在有幾個不重複的字串。

這就簡單了,桶排一下就好了,新加的作為左邊,原來的作為右邊(已排序)。用左邊的字元劃分檔次,原順序不變的填入響應的檔次裡,排好了,重複的合併一下就ok了。

事實上,我們的假設:把第一步的字串從大到小標記好了。是可以成立的,因為一開始是計算單個字元的rank排名。

舉個例子:

字串:aabab

長度為1子串有5個:a,a,b,a,b 給個預設排名:1,2,3,4,5進行一波桶排,第乙個字元為』a』的為第一檔次,排名序號為:1-3 『b』:4-5 同一檔次,根據預設排名的先後,區分先後。

初步排名更新為:1,2,4,3,5(這個排名留著等下還有用)

然後進行精確排名:從第2名開始,比較自己與前一名子串的第乙個字元和剩餘字元是否都相同(這裡只有1個字元,就只比較這1個字元),若都相同則並列名次(廢話,大家都是100分,當然並列第一名嘍)。2與1比較,大家都是』a』;3與2比較,大家都是』a』;5與4比較,大家都是』b』。所以精確排名更新為:1,1,2,1,2

叮!總子串數+2

然後是長度為2:a-a,a-b,b-a,a-b 很明顯,取長度1子串後面4個,前面加上1個字元。它們通過第一步是有初始排名的(同理 第一步的預設排名),這裡取第一步的初步排名:2,4,3,5 **斷了,就後面的都前進1 -->1,3,2,4進行一波桶排,'a』檔次有三個,佔掉前三:1-3 『b』:4 同一檔次,根據初始排名的先後,區分先後。

初步排名更新為:1,2,4,3

精確排名:(比較相鄰排名,左部和右部是否都相同)1,2,3,2

叮!總子串+3

長度為3:a-ab,a-ba,b-ab初始排名:2,4,3->1,3,2

初步排名:1,2,3

精確排名:1,2,3

叮!總子串+3

叮!!未發現並列,執行清算(如果某長度不存在重複,那麼在前面加字元還是不重複的)總子串+2+1.

再來乙個例子:ababac

長度1:

預設排序:1,2,3,4,5,6

初步排序:1,4,2,5,3,6

精確排序:1,2,1,2,1,3 叮+3

長度2:

初始排序:4,2,5,3,6->3,1,4,2,5 取上一步初步排序的後n-1個

初步排序:1,4,2,5,3

精確排序:1,3,1,3,2 叮+3

長度3:

初始排序:4,2,5,3->3,1,4,2

初步排序:1,3,2,4

精確排序:1,2,1,3 叮+3

長度4:

初始排序:3,2,4->2,1,3

初步排序:1,3,2

精確排序:1,3,2 叮+3

叮叮+2+1(長度為5,6的不用算了,肯定沒有重複的)

**:

//求不重複子串數

#include

using

namespace std;

const

int max =

1e6+5;

char s[max]

;int m, n;

//m是種類數量,n是字串長度

long

long sum =0;

//不重複子串數

int rak[max]

, tp[max]

, sa[max]

, tax[max]

;//rak i是位置 rak[i]表示第i個位置的排名是多少

//sa i是排名 sa[i]表示第i名的位置是多少

voi***(

int tt,

int nn = n)

//輸出陣列,除錯的時候用的

cout << endl;

}void

finallyadd

(int x)

//當一種長度的子串不存在重複的,那麼它後面的也肯定不會重複

void

sort2

(int a,

int b)

//a未使用

bool

comp

(int r,

int a,

int b,

int k =1)

//若左部和右部都相同,精確排名不增加

return r[a + k]

== r[b + k]

&& s[a]

== s[b]

;//r + s可以判斷是否相同。

}void

get_sa

(int a,

int b)

}}intmain()

執行結果截圖:

求最長重複子串 和 最長不重複子串 思路

題目 求任意乙個字串中的所有最長重複字串和所有最長不重複子串 最長不重複子串的解法 設定乙個輔助資料結構 如map 記錄每個字元最後一次出現的位置 遍歷字串中的每個字元,如果在map中沒有出現,則不重複子串的長度 1,並更新最大字串的長度值 如果在map中已經出現過,則更新當前字元在map中的位置和...

最長不重複子串

出處 勇幸 thinking 題 從乙個字串中找到乙個連續子串,該子串中任何兩個字元不能相同,求子串的最大長度並輸出一條最長不重複子串。本節從最直接的方法逐步優化,漸進探索了四種實現方式,並最終找到時間複雜度為o n 輔助空間為常數的方案,內容如下 基本演算法 使用hash dp方案 dp hash...

最長不重複子串

演算法參考 找到乙個字串中的乙個連續子串,這個子串內不能有任何兩個字元是相同的,並且這個子串是符合要求的最長的。例如輸入 abcbef 輸出 cbef o n 的演算法,具體思路如下 以abcbef這個串為例,用乙個陣列pos記錄每個元素曾出現的下標,初始化為 1。從s 0 開始,依次考察每個字元,...