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