題意: 給出兩個字串, 求他們的最長公共子串
思路: 兩個字串的最長公共子串長度顯然就是兩個字串的所有字尾中的最長公共字首長度. 可以先用乙個沒有出現的字元(便於後面區分字尾是否屬於相同字串)將兩個字串連成乙個字串,再用字尾陣列求其height, sa陣列, 對於當前 i, 通過 sa 陣列區分字尾 i 和 i - 1 是否在同乙個初始字串中, 若不是則用 height[i] 維護答案最大值.
**:
1 #include 2 #include 3 #includeview code4 #include 5
#define rank rank
6using
namespace
std;78
const
int maxn = 2e5 + 10;9
10char
str[maxn];
11int
sa[maxn], rank[maxn], height[maxn], sum[maxn], tp[maxn];
12//
rank[i] 第i個字尾的排名, sa[i] 排名為i的字尾的位置, height[i] 排名為i的字尾與排名為(i-1)的字尾的lcp
13//
sum[i] 基數排序輔助陣列, 儲存小於i的元素有多少個, tp[i] rank的輔助陣列(按第二關鍵字排序的結果),與sa意義一樣
1415
bool cmp(int *f, int x, int y, int
w)18
19void get_sa(char *s, int n, int
m)33
//tp[i]儲存按第二關鍵字排序第i的下標
34//
對第二關鍵字排序的結果再按第一關鍵字排序,和長度為1的情況類似
35for(int i = 0; i < m; i++) sum[i] = 0;36
for(int i = 0; i < n; i++) sum[rank[tp[i]]]++;
37for(int i = 1; i < m; i++) sum[i] += sum[i - 1
];38
for(int i = n - 1; i >= 0; i--) sa[--sum[rank[tp[i]]]] =tp[i];
39//
根據sa和rank陣列重新計算rank陣列
40 swap(rank, tp);//
交換後tp指向舊的rank陣列
41 p = 1
;42 rank[sa[0]] = 0;43
for(int i = 1; i < n; i++)
46if(p >= n) break
;47 m = p;//
下次基數排序的最大值48}
49//
求height
50int k = 0
;51 n--;
52for(int i = 0; i <= n; i++) rank[sa[i]] =i;
53for(int i = 0; i < n; i++)59}
6061
int main(void
)75 printf("
%d\n
", sol);76}
77return0;
78 }
HDU1403 字尾陣列,模板,入門)
解題思路 字尾陣列的寫法一開始看有些匪夷所思,花了我半天時間才解析完,理解內涵。關於height,詳見我的另一篇字尾陣列分組中的部落格。也推薦幾篇 解析 原理講解 原理講解 題意 給出兩個字串,求他們的最長公共子串 字尾陣列建立字尾優先順序的複雜度為o nlogn n為字串的長度。用height求解...
HDU 1403 字尾陣列初步
題意 求兩個串的最長公共子串 兩個串連線起來然後求高度陣列 注意兩個sa值必須分別在不同一側 本題是用來測試模板的,回想起青島那次翻車感覺很糟糕 include include include include include include include include include inclu...
hdu1403 字尾陣列入門題
1403 思路 字串的任何乙個子串都是這個字串的某個字尾的字首,則求a和b的最長公共子串等價於求a的字尾和b的字尾的最長公共字首的最大值。做法 將第二個字串寫在第乙個字串後面,中間用乙個沒有出現過的字元隔開,再求這個新的字串的字尾陣列。1 include bits stdc h 2 using na...