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