哈希专题--Codeforces
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希专题--Codeforces相关的知识,希望对你有一定的参考价值。
哈希专题–Codeforces
245H Queries for Number of Palindromes
求区间回文串个数, n ≤ 5 × 1 0 3 , q ≤ 1 0 6 n\\le 5\\times 10^3,q\\le 10^6 n≤5×103,q≤106
这范围,显然预处理。
首先维护一个数组 g [ l ] [ r ] g[l][r] g[l][r]表示该区间是否为回文串。
然后维护答案数组
f
[
l
]
[
r
]
f[l][r]
f[l][r]
g
[
l
]
[
r
]
=
g
[
l
+
1
]
[
r
−
1
]
&
a
[
l
]
=
=
a
[
r
]
f
[
l
]
[
r
]
=
f
[
l
+
1
]
[
r
]
+
f
[
l
]
[
r
−
1
]
−
f
[
l
+
1
]
[
r
−
1
]
+
g
[
l
]
[
r
]
\\large g[l][r]=g[l+1][r-1]\\& a[l]==a[r] \\\\ \\large f[l][r]=f[l+1][r]+f[l][r-1]-f[l+1][r-1]+g[l][r]
g[l][r]=g[l+1][r−1]&a[l]==a[r]f[l][r]=f[l+1][r]+f[l][r−1]−f[l+1][r−1]+g[l][r]
注意初始化: f [ i ] [ i ] = g [ i ] [ i ] = g [ i + 1 ] [ i ] = 1 \\large f[i][i]=g[i][i]=g[i+1][i]=1 f[i][i]=g[i][i]=g[i+1][i]=1
for(int i=1;i<=n;i++) f[i][i]=g[i][i]=g[i+1][i]=1;
for(int k=2;k<=n;k++)
for(int i=1,j=k;j<=n;i++,j++){
g[i][j]=g[i+1][j-1]&&(a[i]==a[j]);
f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1]+g[i][j];
}
533E Correcting Mistakes
构造答案, A x B y C AxByC AxByC, x , y x,y x,y分别为两串要删的。
双指针删取前后缀 A , C A,C A,C。
然后特判
B
B
B是否相同即可,有两种情况:
x
B
B
y
−
−
−
B
y
x
B
xB \\\\ By \\\\ ---\\\\ By \\\\ xB
xBBy−−−ByxB
都满足的是情况:
B
B
B为空。这样答案可为:
x
y
,
y
x
xy,yx
xy,yx。
for(i=0;a[i]==b[i];i++);
for(j=n-1;a[j]==b[j];j--);
for(k=i;k<j&&a[k]==b[k+1];k++);
if(k==j) s++;
for(k=i;k<j&&b[k]==a[k+1];k++);
if(k==j) s++;
D. Palindromic characteristics
较水的dp+差分前缀和。
p[0]=1;
for(int i=1;i<=n;i++){
p[i]=p[i-1]*base,h[i]=h[i-1]*base+(a[i]-'a'+1);
g[i][i]=f[i][i]=g[i+1][i]=1;
}
for(int k=2;k<=n;k++)
for(int i=1,j=k;j<=n;i++,j++){
f[i][j]=f[i+1][j-1]&&(a[i]==a[j]);
int l=k>>1;
ull lh=hs(i,i+l-1),rh=hs(j-l+1,j);
if(lh==rh){
int mn=min(f[i][i+l-1],f[j-l+1][j]);
if(mn) f[i][j]=mn+1;
}
}
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++){
int x=f[i][j];
if(x){
ans[1]++,ans[x+1]--;
}
}
for(int i=1;i<=n;i++) ans[i]+=ans[i-1];
D. New Year and Ancient Prophecy
数字字符串分割成严格递增序的方案数。
令 f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i个字符最后一个数字长为 j j j的方案数。
显然最后一段首字符不能为 0 0 0。
然后所有最后一段小于 j j j的都可以递推过来。
令 s u m [ i ] [ j ] sum[i][j] sum[i][j]表示前 i i i个字符最后一段长度小于等于 j j j的方案数。
则: f [ i ] [ j ] + = s u m [ i − j ] [ j − 1 ] f[i][j]+=sum[i-j][j-1] f[i][j]+=sum[i−j][j−1]
然后只需特判长度为 j j j的是否能转移过来, f [ i − j ] [ j ] f[i-j][j] f[i−j][j]
即比较两段数字大小。这里我们可以用 l c s ( l o n g e s t c o m m o n s u f f i x ) lcs(longest \\ common\\ suffix) lcs(longest common suffix)
g [ i ] [ j ] g[i][j] g[i][j] 下标从 i i i开始和从 j j j开始最长的公共后缀。
预处理 g [ i ] [ j ] = ( s [ i ] = = s [ j ] ) ? g [ i + 1 ] [ j + 1 ] + 1 : 0 g[i][j]=(s[i]==s[j])?g[i+1][j+1]+1:0 g[i][j]=(s[i]==s[j])?g[i+1][j+1]+1:0
然后特判时我们只需比较 s [ i + g [ i ] [ j ] ] , s [ j + g [ i ] [ j ] ] s[i+g[i][j]],s[j+g[i][j]] s[i+g[i][j]],s[j+g[i][j]]
注意 g [ i ] [ j ] < g[i][j]< g[i][j]<最后一段的长度。
然后初始化的注意初始化: s u m [ 0 ] [ i ] = 1 sum[0][i]=1 sum[0][i]=1
void lcp(){
for(int i=n;i;i--)
for(int j=n;j>=i;j--)
g[i][j]=(s[i]==s[j])?g[i以上是关于哈希专题--Codeforces的主要内容,如果未能解决你的问题,请参考以下文章
[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段