題意
傳送門 poj 3415
題解
子串是原串中連續的一段,也可以定義為字首的字尾或字尾的字首。統計分別屬於 a,b
a,ba,
b 的不小於 k
kk 的子串個數,那麼將 a,b
a,ba,
b 用乙個不屬於這兩個串的字元拼接起來(避免拼接位置對結果產生影響),構造字尾陣列以及高度陣列(lcp
[i
]lcp[i]
lcp[i]
為 a[i]
,sa[
i+1]
a[i],sa[i+1]
a[i],s
a[i+
1]的最長公共字首)。設任意兩個字尾在字尾陣列中的索引分別為 i,j
(i
i,j(ii, j(i,此時可以快速地求解它們的最長公共字首,即 m in min\ min 那麼答案為 ∑ i= 0n∑j =i+1 nmax (0,m in), sa[i ]∈a, sa[j ]∈ b\sum\limits_^\sum\limits_^max\big(0,min\\big),sa[i]\in a,sa[j]\in b i=0∑n j=i+ 1∑n max( 0,mi n),s a[i] ∈a,s a[j] ∈b字尾陣列 + 單調棧 m in minmi n 函式有隨著區間的擴大值單調不增的性質,那麼從左向右掃瞄高度陣列,維護乙個單調遞增棧,統計分別屬於 a,b a,ba, b 的字尾與當前右界代表的字尾在單調遞增的最長公共字首中的數量,同時統計當前右界可以與左邊的字尾構成的三元組數量。#include
#include
#include
using
namespace std;
#define maxn 100005
typedef
long
long ll;
string a, b;
int n, k, na, limit, rnk[maxn <<1]
, tmp[maxn <<1]
, sa[maxn <<1]
, lcp[maxn <<1]
;bool
cmp_sa
(int i,
int j)
void
construct_sa
(string &s,
int*sa)
for(k =
1; k < n; k <<=1)
}void
construct_lcp
(string &s,
int*sa,
int*lcp)
}struct node
st[maxn <<1]
;ll solve()
, h = lcp[i]
- limit +1;
++sz[id]
;while
(top >
0&& h <= st[top -1]
.h)}
st[top]
.sz[0]
= sz[0]
, st[top]
.sz[1]
= sz[1]
, st[top]
.h = h;
++top;
for(
int j =
0; j <2;
++j)
cnt[j]+=
(ll)sz[j]
* h;
int id2 = sa[i +1]
< na;
res +
= cnt[id2 ^1]
;}}return res;
}int
main()
return0;
}字尾陣列 + 並查集
由於字尾陣列的有序性,最長相同公共字首不小於 k
kk 的字尾在字尾陣列中是處於連續位置的,那麼可以依次掃瞄求出這樣的連續位置。但對於任意一對字尾,需要 rmq
rmqrm
q 求解最長公共字首,直接列舉複雜度 o(n
2)
o(n^2)
o(n2
) 難以勝任,考慮從有最大值的最長公共字首的字尾對 (i,
j)
(i,j)
(i,j
) 開始統計,那麼已統計過的字尾對也必然滿足小於這個值的公共字首。
運用高度陣列以並查集維護位於屬於同乙個連續位置的字尾,此時就可以只進行一次列舉高度的處理,從大到小依次統計有這樣長度的公共字首的字尾對,在合併操作時統計新增的字尾對數。
#include
#include
#include
#include
using
namespace std;
#define maxn 100005
typedef
long
long ll;
string a, b;
int n, k, na, limit, rnk[maxn <<1]
, tmp[maxn <<1]
, sa[maxn <<1]
, lcp[maxn <<1]
;bool
cmp_sa
(int i,
int j)
void
construct_sa
(string &s,
int*sa)
for(k =
1; k < n; k <<=1)
}void
construct_lcp
(string &s,
int*sa,
int*lcp)
}typedef pair<
int,
int> p;
int par[maxn <<1]
, rk[maxn <<1]
, cnt[maxn <<1]
[2];
vectorhs[maxn]
;int
find
(int x)
ll unite
(int x,
int y)
ll solve()
int maxh =
max(na, n -
1- na)
;for
(int i = limit; i <= maxh;
++i)
hs[i]
.clear()
;for
(int i =
0; i < n;
++i)
ll res =
0, sum =0;
for(
int i = maxh; i >= limit;
--i)
res +
= sum;
}return res;
}int
main()
return0;
}
POJ 3415 字尾陣列 單調棧
簡略題意 求兩個串長度不小於k的公共子串的個數。我喜歡這題!首先按height分組,隨後對於每個a字尾,看之前出現的b字尾與其的lcp,若其長度為 x 則對答案的貢獻為x k 1。暴力查詢n2 其實b字尾的排名越接近當前a字尾,兩者的lcp越高 想一想,為什麼,因此維護乙個單調棧,以及棧內元素貢獻總...
POJ 3415 字尾陣列 單調棧 並查集
大致題意 現給定字串s和t 求s和t的長度不小於k的公共子串個數 題目思路 對於s的每乙個字尾和t的每乙個字尾求lcp,如果匹配出的lcp x,那麼ans x k 1 x k 直接暴力顯然不行,就有了下面的方法 將兩個串做連線得到字串str,中間隔乙個絕對不會出現的任意字元,比如 得到str s t...
poj 3415 字尾陣列 單調佇列
common substrings time limit 5000ms memory limit 65536k total submissions 8106 accepted 2688 description a substring of a string t is defined as t i,k...