hdu4622
字尾陣列基礎題?
昨天學了字尾排序其實最有用的是字尾陣列求lcp
lcplc
p?用了乙個hei
ght[
i]=l
cp(s
a[i]
,sa[
i−1]
)height[i]=lcp(sa[i],sa[i-1])
height
[i]=
lcp(
sa[i
],sa
[i−1
]),也就是排名為i
ii的和排名i−1
i-1i−
1的字尾的lcp
lcplc
p為了方便,設h[i
]=he
ight
(rk[
i]
)h[i]=height(rk[i])
h[i]=h
eigh
t(rk
[i])
就是i
ii位置的字尾和它前一名的字尾的lcp
lcplc
p 有幾個性質:
h [i
]≥h[
i−1]
+1
h[i]\ge h[i-1]+1
h[i]≥h
[i−1
]+1,證明可以感性理解一下,把i−1
i-1i−
1和它的上一名同時去掉第一位就是h[i
]h[i]
h[i]
有了這個就可以快速求出h
hh陣列:
inline
void
geth()
}
還有lcp
(i,j
)=mi
ni+1
≤k≤j
(h[k
])
lcp(i,j)=min_(h[k])
lcp(i,
j)=m
ini+
1≤k≤
j(h
[k])
這個也可以感性理解一下,手動模擬之類的
有了這個就可以快速求出lcp
lcplc
p,這道題中套乙個stst
st表求區間最小值就好了
inline
intquery
(int l,
int r)
//st表,區間min
inline
intlcp
(int l,
int r)
然後再回來看這道題,區間[l,
r]
[l,r]
[l,r
]本質不同的子串其實就是所有字尾的長度減去它和之前字尾的lcp
lcplc
p,因為它的lcp
lcplc
p是之前出現過的,然後後面每加乙個字元就可以產生乙個新的。
而且因為字尾排序的特性,不會出現某兩個排名i,j
,k(i
<
j i,j,k(ii, j,k( i< j且l cp (i,k )>lc p(j, k) lcp(i,k)>lcp(j,k) lcp(i, k)>lc p(j, k),所以這個方法是正確的 最後放**:#include
#include
#include
#include
#include
#include
#define maxn 2005
using
namespace std;
inline
intrd()
int t,n,m,q,sa[maxn]
,rk[maxn]
,tp[maxn]
,tax[maxn]
,h[maxn]
,st[maxn][12
];char s[maxn]
;inline
void
rsort()
//基數排序
inline
void
ssort()
}//字尾排序
inline
void
geth()
}//求h陣列
void
prework()
inline
intquery
(int l,
int r)
//st表,區間min
inline
intlcp
(int l,
int r)
//求lcp,lcp(i,j)=min(h[k]) i+1<=k<=j
inline
intask
(int l,
int r)
return sum;
}int
main()
}return0;
}
字尾陣列 HDU 4436
做法 首先應用求不同子串的演算法,自然想到字尾陣列,然後就是要統計以非 0 開始的字尾。考慮字尾 akak 1ak 2.an tmp 0 ak 0 tmp i tmp i 1 10 ai 0 sum i sum i 1 tmp i 那麼 以 am開始的字首和就是 sum n sum m 1 tmp ...
hdu 3518 字尾陣列
晚飯前寫的 一直wa,一直想不通,後來寫程式對拍了,一百組資料中錯了一組,然後還是想不通為什麼的,然後的然後看了別人的 然後瞬間知道自己為什麼wa!還是對字尾陣列了解的不夠,自己預設的是sa中排在前面的然後在字串陣列中下標也是在前面的,然後就沒有挨個比較相同長度中的取最大值和最小值,所以wa的可憐啊...
hdu 3518 字尾陣列
字尾陣列的題目主要是對三個陣列的利用 sa 記錄的是排名為i的字尾的首字母的下標 1 n rank 記錄的是首字母下標為i的字尾的排名 n height 記錄是j和j 1排序的最長公共字首 這道題求取的是不重疊的最少出現兩次的子串的個數 根據height j 陣列的性質,列舉長度然後按順序遍歷i,如...