最近在跟着 罗穗骞 的论文学习后缀数组, 不亏是神牛的论文。无论是算法讲解,还是习题举例都非常不错。下面把最进做的几道后缀数组整理一下。
1.两字符串的最长公共子串
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <sstream> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <limits.h> 8 #include <vector> 9 #include <string> 10 #include <time.h> 11 #include <math.h> 12 #include <queue> 13 #include <stack> 14 #include <set> 15 #include <map> 16 #define INF 0x3f3f3f3f 17 #define Zero(x) memset((x),0, sizeof(x)) 18 #define Neg(x) memset((x), -1, sizeof(x)) 19 #define dg(x) cout << #x << " = " << x << endl 20 #define pk(x) push_back(x) 21 #define pok() pop_back() 22 #define eps 1e-8 23 #define pii pair<int, int> 24 #define pi acos(-1.0) 25 using namespace std; 26 typedef long long ll; 27 bool debug = true; 28 int OK = 1; 29 const int maxn = 220000; 30 int sa[maxn], r[maxn], height[maxn], t1[maxn], t2[maxn], c[maxn]; 31 int rk[maxn]; 32 char str[maxn]; 33 bool cmp(int *r, int a,int b, int l){ 34 return r[a] == r[b] && r[a + l] == r[b + l]; 35 } 36 37 void da(int str[], int sa[], int rk[], int height[], int n, int m){ 38 n++; 39 int i, j, p, *x = t1, *y = t2; 40 for(i = 0; i < m; i++) c[i] = 0; 41 for(i = 0; i < n; ++i) c[x[i] = str[i]]++; 42 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 43 for(i = n - 1; i >= 0; --i) sa[--c[x[i]]] = i; 44 for(j = 1; j <= n; j <<= 1){ 45 p = 0; 46 for(i = n - j; i < n; ++i) y[p++] = i; 47 for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; 48 for(i = 0; i < m; ++i) c[i] = 0; 49 for(i = 0; i < n; ++i) c[x[y[i]]]++; 50 for(i = 1; i < m; ++i) c[i] += c[i - 1]; 51 for(i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; 52 swap(x, y); 53 p = 1; x[sa[0]] = 0; 54 for(i = 1; i < n; ++i) 55 x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1: p++; 56 if(p >= n) break; 57 m = p; 58 } 59 int k = 0; 60 n--; 61 for(i = 0; i <= n; ++i) rk[sa[i]] = i; 62 for(i = 0; i <n ; ++i){ 63 if(k) k--; 64 j = sa[rk[i] - 1]; 65 while(str[i + k] == str[j + k]) ++k; 66 height[rk[i]] = k; 67 } 68 } 69 int main(){ 70 //freopen("data.in","r",stdin); 71 //freopen("data.out","w",stdout); 72 //cin.sync_with_stdio(false); 73 while(scanf("%s", str) != EOF){ 74 int len = strlen(str); 75 int len1 = len; 76 str[len] = '9'; 77 scanf("%s", str + len + 1); 78 len = strlen(str); 79 for(int i = 0; i < len; ++i) r[i] = str[i]; 80 r[len] = 0; 81 da(r, sa, rk, height, len, 128); 82 int mx = 0; 83 for(int i = 2; i < len; ++i){ 84 if(mx < height[i] && (sa[i] > len1 && sa[i - 1] < len1 || sa[i] < len1 && sa[i - 1] > len1)){ 85 mx = height[i]; 86 } 87 } 88 cout << mx << endl; 89 } 90 return 0; 91 }