哈希专题--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 n5×103,q106

这范围,显然预处理。

首先维护一个数组 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][r1]&a[l]==a[r]f[l][r]=f[l+1][r]+f[l][r1]f[l+1][r1]+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 xBByByxB
都满足的是情况: 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[ij][j1]

然后只需特判长度为 j j j的是否能转移过来, f [ i − j ] [ j ] f[i-j][j] f[ij][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](代码片段

《寒假算法集训》(专题十三)哈希

下文中的哈希片段指的是啥?

codeforces的dp专题

URL片段的最大长度(哈希)

URL的PHP​​和哈希/片段部分