字尾陣列學習筆記

2021-12-29 22:31:27 字數 4313 閱讀 6462

要用好字尾陣列要先理解裡面幾個陣列的概念:

sa[i]表示字典序第i大的字尾下標(字典序排名依次是1?len(string));

rank[i]表示下標為i的字尾字典序排名;

height[i]表示sa[i]和sa[i?1]最長公共字首的長度.

乙個性質: lcp(suffix[i],suffix[j])=min(rank[i]

倍增法求出這些陣列, 記得在原串的末尾增加乙個0:

int t1[maxn],t2[maxn],c[maxn];

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

void da(int str,int sa,int rank,int height,int n,int m)

int k = 0;

n--;

for(i = 0; i <= n; i++)rank[sa[i]] = i;

for(i = 0; i < n; i++)

}poj 1743 最長不重疊相同子串

題意: 求兩個最長的不重疊子串, 滿足兩個串對應下標的差值相等.

對於相鄰的兩個數直接做差得到乙個新串, 直接對新串求最長不重疊子串. 非常經典的做法, 二分長度, 然後對height陣列分組, 滿足這個長度的分成一組, 然後判斷組中下標最大最小之差.

資料很水~

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define maxn 20005

using namespace std;

int t1[maxn],t2[maxn],c[maxn];

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

void da(int str,int sa,int rank,int height,int n,int m)

int k = 0;

n--;

for(i = 0; i <= n; i++)rank[sa[i]] = i;

for(i = 0; i < n; i++)

}int rank[maxn], height[maxn];

int str[maxn];

int sa[maxn];

int n;

#define inf 111111

bool ok (int x)

else

}return max-min >= x;

}int solve ()

return (ok (r) ? r : l);

}int main()

if (n <= 9)

n--;

for (int i = 0; i < n; i++)

str[n] = 0;

da(str, sa, rank, height, n+1, 188);

int ans = solve ()+1;

printf ("%d\n", (ans >= 5 ? ans : 0));

}return 0;

}poj 3261 求重複k次的最長子串

還是二分結果, 按照height分組, 判斷是不是有大於k的組.

資料還是很水, 不加離散化都能過~

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define maxn 200005

using namespace std;

int t1[maxn],t2[maxn],c[maxn];

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

void da(int str,int sa,int rank,int height,int n,int m)

int k = 0;

n--;

for(i = 0; i <= n; i++)rank[sa[i]] = i;

for(i = 0; i < n; i++)

}int rank[maxn], height[maxn];

int str[maxn];

int sa[maxn];

int n, k;

bool ok (int x)

else

ans = 1;

}return 0;

}int solve ()

return (ok (r) ? r : l);

}int cnt, num[maxn], gg[maxn];

int lisanhua ()

int main()

str[n] = 0;

int m = lisanhua ();

da (str, sa, rank, height, n, m+2);

int ans = solve ();

cout << ans << endl;

}return 0;}/*

2 21 1

*/spoj 694 不重複子串個數

根據sa陣列和height陣列的含義, sa[i]字尾總共有n?sa[i]個字首, 有height[i]個字首和之前的重複, 所以要減去. 最後答案是∑ni=1n?sa[i]?height[i].

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define maxn 200005

using namespace std;

int t1[maxn],t2[maxn],c[maxn];

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

void da(int str,int sa,int rank,int height,int n,int m)

int k = 0;

n--;

for(i = 0; i <= n; i++)rank[sa[i]] = i;

for(i = 0; i < n; i++)

}int rank[maxn], height[maxn];

int str[maxn];

char s[maxn];

int sa[maxn];

int n, k;

int main()

cout << ans << endl;

}return 0;

}poj 2774 最長公共子串

把第二個串放到第乙個串的後面, 中間用乙個失配符隔開, 然後遍歷height陣列維護最大子串長度. 要避免出現在同一串中的公共子串.

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define maxn 200005

using namespace std;

int t1[maxn],t2[maxn],c[maxn];

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

void da(int str,int sa,int rank,int height,int n,int m)

int k = 0;

n--;

for(i = 0; i <= n; i++)rank[sa[i]] = i;

for(i = 0; i < n; i++)

}int rank[maxn], height[maxn];

int str[maxn];

char s1[maxn], s2[maxn];

int sa[maxn];

int n, m, len;

bool legal (int i, int j)

void solve ()

cout << max << endl;

}int main()

return 0;

}

字尾陣列學習筆記

要用好字尾陣列要先理解裡面幾個陣列的概念 sa i 表示字典序第i大的字尾下標 字典序排名依次是1 len stri ng ra nk i 表示下標為i的字尾字典序排名 he ight i 表示sa i 和sa i 1 最長公共字首的長度.乙個性質 lc p su ffix i suff ix j ...

字尾陣列 學習筆記

字尾陣列是處理字串的強有力的工具 在字串處理當中,字尾樹和字尾陣列都是非常有力的工具。其實字尾陣列是字尾樹的乙個非常精巧的替代品,它比字尾樹容易程式設計實現,能夠實現字尾樹的很多功能而時間複雜度也不太遜色,並且,它比字尾樹所占用的空間小很多。可以說,在資訊學競賽中字尾陣列比字尾樹要更為實用。我們定義...

字尾陣列 學習筆記

剛剛學完回文自動機 來學字尾陣列 一開始思路看得懂 但是 看不懂呀 一堆神仙 洛谷p3809 勿謂我,何強過者,炸哉!我們需要一種新的演算法 字尾陣列 首先,輸入字串 scanf s ch 1 n strlen ch 1 然後,按照題意 suffix sort ch for int i 1 i n ...