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

2022-05-02 06:39:10 字數 2959 閱讀 6327

大致題意:現給定字串s和t ,求s和t的長度不小於k的公共子串個數;

題目思路:

對於s的每乙個字尾和t的每乙個字尾求lcp,如果匹配出的lcp=x,那麼ans+=x-k+1(x>=k),直接暴力顯然不行,就有了下面的方法:

將兩個串做連線得到字串str,中間隔乙個絕對不會出現的任意字元,比如『#』,得到str = s + '#' + t 。

再對str求sa和height(加『#』的目的是為了讓height陣列的值不超過s和t的長度。例如s=『aaaaa』,t=『aaaa』,直接連線的話,顯然會使height的值過大,根據height[i]的定義是排名i和i-1的最長公共字首)

lcp(i,j) = min ( height[i+1] , height[i+2] , ... , height[j] ) ;

對於排名為j且屬於t串的字尾,直接求所有的lcp(i,j) 之和,其中i∈s且 i < j ,顯然lcp(i,j) 與 lcp(i,j+1) 是有聯絡的(多了乙個數字取min,lcp(i,j) <= lcp(i,j+1) ),因此就沒必要重複計算

那麼根據排名從小到大進行掃瞄,並且根據其height值維護乙個單調棧(單增棧),單調棧的作用是維護[1,i-1] 中的s對 i 的貢獻 

另一種思路,可以直接用並查集來算,也是可行的;

#include#include

#include

#include

#include

#pragma gcc optimize(2)

using

namespace

std;

//std::mt19937 rnd(233);

typedef long

long

ll;typedef pair

pii;

typedef pair

pll;

#define pb push_back

#define mk make_pair

#define fi first

#define se second

#define ls (i<<1)

#define rs (i<<1|1)

#define mem(a,b) memset(a,b,sizeof(a))

const

int n=1e6+5

;const

int inf=0x3f3f3f3f

;const ll mod=1e9+7

;ll read()

while(isdigit(ch))

return f*x;

}int

sa[n],rk[n],x[n],y[n],he[n],c[n],n,m,sta[n],num[n];

char

s[n],s1[n];

void

sa()

}void

gethe()

}int

main()

}for(int i=1;i<=n;i++)//

對於每乙個i算出[1,i-1]對i點的貢獻res

}printf(

"%lld\n

",ans);

for(int i=1;i<=n;i++) x[i]=y[i]=0

; }

return0;

}

單調棧

1 #include2 #include3 #include4 #include5 #include6

#pragma gcc optimize(2)

7using

namespace

std;

8 typedef long

long

ll;9 typedef pairpii;

10 typedef pairpll;

11#define pb push_back

12#define mk make_pair

13#define fi first

14#define se second

15#define ls (i<<1)

16#define rs (i<<1|1)

17#define mem(a,b) memset(a,b,sizeof(a))

18const

int n=1e6+5;19

const

int inf=0x3f3f3f3f;20

const ll mod=1e9+7;21

ll read()

2226

while(isdigit(ch))

27return f*x;28}

29pii a[n];

30int

sa[n],rk[n],he[n],x[n],y[n],c[n],n,m,f[n],cs[n],ct[n];

31char

s[n],t[n];

32void

sa()

335556}

57void

gethe()

5869}70

int getf(int

x)71

74int

main()

7591

for(int i=1;i<=n;i++) a[i]=mk(he[i],i);

92 sort(a+1,a+n+1

);93 ll ans=0;94

//for(int i=1;i<=n;i++) printf("%d%c",sa[i],i==n?'\n':' ');

95for(int i=n;i;i--)

96108 printf("

%lld\n

",ans);

109for(int i=1;i<=n;i++) x[i]=y[i]=0

;110

}111

return0;

112 }

並查集

POJ 3415 字尾陣列 單調棧

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

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

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

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...