字尾陣列學習筆記

2021-07-15 22:27:54 字數 4790 閱讀 1943

要用好字尾陣列要先理解裡面幾個陣列的概念: 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

])=m

in(r

ank[

i]nk[j

])倍增法求出這些陣列, 記得在原串的末尾增加乙個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;

}return0;}

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;

}return0;}

/*2 2

1 1*/

spoj 694 不重複子串個數根據s

a 陣列和he

ight

陣列的含義, sa

[i] 字尾總共有n−

sa[i

] 個字首, 有he

ight

[i] 個字首和之前的重複, 所以要減去. 最後答案是∑n

i=1n

−sa[

i]−h

eigh

t[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;}

字尾陣列 學習筆記

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

字尾陣列 學習筆記

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

字尾陣列學習筆記

要用好字尾陣列要先理解裡面幾個陣列的概念 sa i 表示字典序第i大的字尾下標 字典序排名依次是1?len string rank i 表示下標為i的字尾字典序排名 height i 表示sa i 和sa i?1 最長公共字首的長度.乙個性質 lcp suffix i suffix j min ra...