time limit: 20 sec
memory limit: 128 mb
submit: 1767
solved: 438 [
submit][
status][
discuss]
輸入第1行,包含3個整數n,q。q代表詢問組數。
第2行是字串s。
接下來q行,每行兩個整數i和j。(1≤i≤j)。
輸出共q行,每行乙個數表示每組詢問的答案。如果不存在第i個子串或第j個子串,則輸出-1。
5 3ababa
3 55 9
8 10
1816
-1樣例解釋
第1組詢問:兩個子串是「aba」,「ababa」。f = 32 + 32 = 18。
第2組詢問:兩個子串是「ababa」,「baba」。f = 02 + 42 = 16。
第3組詢問:不存在第10個子串。輸出-1。
資料範圍
n≤100000,q≤100000,字串只由小寫字母'a'~'z'組成
字尾陣列+二分+rmq
【分析】
不得不說我已經把字尾陣列的題寫成黑箱題了...
又是一道手玩出來的題...
搞乙個原串的字尾陣列,再搞乙個反串的...
分別搞一下lcp就行了...
不過我還是不太清楚為什麼是lower_bound,總感覺是upper_bound-1才對啊...腦洞開了改了一下就a掉了...= =
以上的話當p處理...窩腦子water了...
【**】
//bzoj 3230 相似子串
#include#include#include#include#define ll long long
#define m(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=100005;
int m,q;
char s[mxn];
ll cnt[mxn];
ll sum,len,u,v;
inline ll read()
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
} inline void work()
p=k=0;
fo(i,1,len) rank[sa[i]]=i;
for(i=1;i<=len;height[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];a[i+k]==a[j+k];k++);
}inline void init()
int tu=lower_bound(cnt+1,cnt+len+1,u)-cnt;
int tv=lower_bound(cnt+1,cnt+len+1,v)-cnt;
int tu=u-cnt[tu-1]+a.sa[tu]+a.height[tu]-1;
int tv=v-cnt[tv-1]+a.sa[tv]+a.height[tv]-1;
ll start=min(a.lcp(a.sa[tu],a.sa[tv]),min(tu-a.sa[tu]+1,tv-a.sa[tv]+1));
ll end=min(b.lcp(len-tu+1,len-tv+1),min(tu-a.sa[tu]+1,tv-a.sa[tv]+1));
printf("%lld\n",start*start+end*end);
}return 0;
}
BZOJ 3230 相似子串
給定乙個長度為 n 的字串以及 q 組查詢,每組查詢給定 a 和 b 求在所有本質不同子串中排名第 a 和第 b 的串的最長公共字首與最長公共字尾的平方和.n,q le 1 times 10 5 字尾陣列板子題.麻麻我終於會用字尾陣列辣 本來想接著用sam的.但是發現多組查詢排名為 k 的本質不同子...
BZOJ3230 相似子串
3230 相似子串 time limit 20 sec memory limit 128 mb submit 913 solved 223 submit status description input 輸入第1行,包含3個整數n,q。q代表詢問組數。第2行是字串s。接下來q行,每行兩個整數i和j。...
bzoj3230 相似子串 SA lcp 二分
首先用字尾陣列處理出h陣列。因為要問子串的排名,所以我們再記乙個陣列num i 表示前i個字尾有幾個本質不同的子串。然後我們用二分查詢就可以找到排序後的第i個子串是誰了。然後就是求一下lcp了。還有反過來的lcp。算清角標就好了。還有很坑的一點 可能有超過int範圍個實質不同的字串 include ...