今天學了字尾陣列,感覺好難理解,只能搬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 鄰接表...