poj 3415 字尾陣列 單調佇列

2021-07-02 16:06:21 字數 2188 閱讀 8382

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)=titi

+1...

ti+k

-1, 1≤

i≤i+k-1≤|

t|.given two strings a, b and one integer k, we define s, a set of triples (i, j, k):

s = .

you are to give the value of |s| for specific a, b and k.

input

the input file contains several blocks of data. for each block, the first line contains one integer k, followed by two lines containing strings a and b, respectively. the input file is ended by k=0.

1 ≤ |a|, |b| ≤ 105

1 ≤ k ≤ min

characters of a and b are all latin letters.

output

for each case, output an integer |s|.

sample input

2

aababaa

abaabaa1xx

xx0

sample output

22

5

source

poj monthly--2007.10.06, wintokk

題意是求兩個字串長度》=k的公共子串有多少個。

先考慮怎麼求解公共子串的問題。公共子串可以用字尾陣列求,將兩個字串str1和str2合併為乙個字串,中間插入乙個不會出現的字元做分割。得到字尾陣列和高度陣列,有了高度陣列就可以求出任意兩個字尾的lcp最長公共字首值,lcp即為兩個字尾之間height[i]的最小值。

回到這個問題上,假如兩個分別屬於str1和str2的字尾lcp為x (x>k), 那麼就計數x-k+1個長度》=k的公共子串。那麼答案就是每個屬於str1和每個屬於str2的lcp-k+1求和。

直接列舉要n^2logn複雜度(單次查詢兩個字尾lcp用rmq--logn複雜度)。任意兩個字尾的lcp值取決於它們之間的最小值,直接列舉慢就慢在每兩個字尾都要找一遍它們之間的最小值。利用最小值這個關鍵點,假如列舉以第i個lcp值為最小值的區間[l,r],那麼ans+=(左邊屬於str1的字尾個數*右邊屬於str2+左邊屬於str2*右邊屬於str1)*(lcp-k+1)。而找到以某個值為最小值的區間用單調佇列左右掃一遍o(n)就可以得到。

#include #include #include #include #include using namespace std;

const int maxn=200005;

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; iheight[i]) tail--;

if(tail+1!=head) lb[i]=que[tail]+1;

else lb[i]=1;

que[++tail]=i;

}head=0, tail=-1;

for(int i=n; i>=1; i--)

memset(sum, 0, sizeof(sum)); //字首和維護區間內屬於str1的字尾個數

for(int i=1; i<=n; i++){

if(sa[i]

POJ 3415 字尾陣列 單調棧

簡略題意 求兩個串長度不小於k的公共子串的個數。我喜歡這題!首先按height分組,隨後對於每個a字尾,看之前出現的b字尾與其的lcp,若其長度為 x 則對答案的貢獻為x k 1。暴力查詢n2 其實b字尾的排名越接近當前a字尾,兩者的lcp越高 想一想,為什麼,因此維護乙個單調棧,以及棧內元素貢獻總...

POJ 3415 字尾陣列

題意 給定2個串 a串和b串 求兩個串公共子串長度大於等於k的個數。思路 首先是兩個字串的問題。所以想用乙個 把兩個字串拼接起來。求字尾陣列。然後按照k把height陣列分組。大於等於k的為一組,然後就是統計每組的貢獻。對於每一組的貢獻即是組內所有a串的字尾和b串的字尾的lcp值,即為val.那麼v...

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

題意 傳送門 poj 3415 題解子串是原串中連續的一段,也可以定義為字首的字尾或字尾的字首。統計分別屬於 a,b a,ba,b 的不小於 k kk 的子串個數,那麼將 a,b a,ba,b 用乙個不屬於這兩個串的字元拼接起來 避免拼接位置對結果產生影響 構造字尾陣列以及高度陣列 lcp i lc...