POJ 3415 字尾陣列 單調棧 並查集

2021-10-10 19:01:21 字數 3734 閱讀 7736

題意

傳送門 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...