大致題意:現給定字串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...