給了乙個長度為n的字串,要求將其分為k段,求這k段最長的並且字典序最小的lcs.
k ≤n
≤1e5
,∣∑∣
小寫字母
k\le n\le 1e5,|\sum|小寫字母
k≤n≤1e
5,∣∑
∣小寫字
母二分+hash+sa
首先可以把問題轉化為求乙個最長的並且字典序最小的字串,在原串中不重疊地出現了k次.
然後二分這個字串的長度l,因為原串長度為l的字串數量是o(n
)o(n)
o(n)
級別的,所以可以把每個字串的hash值算出來,分成幾種字串,對每種字串計算不重疊出現次數最多是多少,然後判斷兩個字串的字典序需要預處理出sa,然後直接o(1
)o(1)
o(1)
比較兩個字串的開頭所在的字尾大小就可以了.
#include
using
namespace std;
const
int maxn=
1e5+5;
typedef
unsigned
long
long ull;
const ull step=
23,mod=
4115188075855873ll
;//2^57+1再移除前兩位,比較大的模數可以減少hash衝突,畢竟這題不能掛鏈
inline
intread()
while
(isdigit
(c))
return t*f;
}int n,k;
int x[maxn]
,y[maxn]
,sa[maxn]
,rk[maxn]
,m=300
,t[maxn]
;char s[maxn]
;void
get(
)swap
(x,y)
;x[sa[1]
]=1;num=1;
for(
int i=
2;i<=n;i++
) x[sa[i]]=
(y[sa[i]
]==y[sa[i-1]
])&&(y[sa[i]
+k]==y[sa[i-1]
+k])
?num:
++num;
if(num==n)
break
; m=num;
}for
(int i=
1;i<=n;i++
)rk[sa[i]
]=i;
}ull ha[maxn]
;int ans;
char alfa[maxn]
;typedef pairint> pii;
pii mp[maxn]
;bool
calc
(int x)
for(
int i=x+
1;i<=n;i++
)int len=n-x+1;
for(
int i=
1;i<=n-x+
1;i++
)sort
(mp+
1,mp+
1+len)
;int lst=
1,bt=
0,flag=0;
for(
int i=
1;i<=len;i++)if
(cnt>=k)}}
} lst=i+1;
}}if(flag&&x>ans)
for(
int i=bt;i)alfa[i-bt]
=s[i]
;return flag;
}int
main()
else r=mid-1;
}if(ans)
else
puts
("kyoma is wrong.");
return0;
}
一道字串練習題
求乙個字串有多少本質不同的子串,這裡的不同指兩個子串的最小表示法不同.n 5 e4,1 a i n 其中n 是字串 長度,a i 是 字元 n 5e4,1 a i n,其中n是字串長度,a i 是字元 n 5 e4,1 a i n 其中n 是字串 長度,a i 是 字元首先,如果不同指字串本身不同,...
一道互動練習題
的做法 考慮逐位確定 對於每個位置,往後列舉有沒有位置可以使得正確位置更多,如果有,那麼有兩種情況,1是這個位置被放到了正確的位置,2是這個位置本來應該放的數被放來了 這裡的重點是我們需要區分1和2 具體的做法是記下讓這個位置答案正確位置數變大的2個位置,將其和i一起移位 這裡是手繪示意圖.即把p1...
一道fft練習題
考場上想到的o n 2 o n 2 o n2 暴力 記f i j f i j f i j 表示前i個位置,長度為j的連擊出現的期望次數 記g i j g i j g i j 表示第到i個位置為止,目前連擊次數為j的概率 轉移時有一些細節 include using namespace std con...