ACM暑期集訓12

2021-08-22 05:02:19 字數 1975 閱讀 8127

今天學了字尾陣列,感覺好難理解,只能搬ppt,粘模板了~~

1)字尾: suffix(i)為從下標i開始的字尾

string = 「abcdef」   suffix(1) = 「bcdef」   suffix(2) = 「cdef」

什麼是字尾陣列?

把乙個字串的所有字尾按字典序進行排序。

字尾陣列sa[i]表示排名為i的字尾下標是什麼,

rk[i]表示下標為i的字尾排名是多少  rk和sa是一種互逆的關係

aabac      sa[1] = 0         rk[0] = 1

abac        sa[2] = 1         rk[1] = 2

string = 「aabac」    ac           sa[3] = 3          rk[2] = 4

bac          sa[4] = 2          rk[3] = 3

c              sa[5] = 4          rk[4] = 5

最樸素的:把所有字尾找出來,總共有n個,進行快速排序,複雜度nlogn 但是字串比較也需要n的複雜度,所以總複雜度n^2logn。

優化:使用倍增和基數排序的方法,複雜度nlogn

2)height陣列

height[i]表示suffix(sa[i])和suffix(sa[i-1])的最長公共字首, 也就是排名i的字尾和排名i-1的字尾的最長公共字首

如何求height

首先定義h[i] = height(rk[i])

有乙個定理h[i] >= h[i-1] -1

注意這裡的i表示字串的下標,也就是字串 下標在每次右移時,它的height一定不會突降2 及以上。

乙個比較明顯的結論:兩個排名越靠近的 字尾,相似度越高。

//倍增演算法 o(n*logn)

//待排序陣列長度為n,放在0~n-1中,在最後麵補乙個0 num[n] = 0

const int maxn = 10000;

char s[maxn];

int wa[maxn],wb[maxn],wv[maxn],wd[maxn],num[maxn],minl[maxn][20],n;

//wa,wb是給關鍵字排序用的臨時陣列

//wd是基數排序用的臨時陣列

//把字串轉化成ascii放在num中

//minl用於查詢區間最小值

int cmp(int *r,int a,int b,int l)

int sa[maxn],rk[maxn],height[maxn];

//注意 最後乙個值即num[n]一定要比所有的都小

void sa(int *r,int n)

//最長回文串

int main()

tmp = lcp(n-i-1,i+1);

if (tmp*2 > maxlen)

}if (maxlen&1)

for (int i=maxpos-maxlen/2;i<=maxpos+maxlen/2;i++)

printf("%c",s[i]);

else

for (int i=maxpos-maxlen/2+1;i<=maxpos+maxlen/2;i++)

printf("%c",s[i]);

printf("\n");

}return 0;

}

ACM暑期集訓2

今天主要學習了線性dp和揹包問題以及快速冪。1.整數快速冪 這個直接粘上 int qpow int x,int n res res res n n 1 return ans 2.矩陣快速冪 主要就是將整數快速冪的乘法運算換做矩陣的乘法 下面的 是方陣的快速冪 const int n 10 int t...

ACM暑期集訓4

今天主要學習了線段樹,樹狀陣列,st表,差分,分塊和樹剖 好吧,這個已經沒聽懂了 1.線段樹 線段樹涉及許多應用和思想,以下是今天所學 線段樹主要用於處理一段連續區間的插入,查詢,統計,查詢等操作。複雜度 設區間長度是n,所有操作的複雜度是logn級別。性質 線段樹是平衡的2叉樹,最大深度logn ...

ACM暑期集訓5

今天主要學習力圖論基礎和最短路徑 1.圖論基礎 1 鄰接矩陣存圖 w i j 表示以ij為頂點的邊的權值 const int n 105,inf 9999999 int dis n w n n vis n n,m 鄰接矩陣存圖 for int i 1 i n i for int i 0 i2 鄰接表...