首页 > 其他分享 >ICPC23沈阳区域赛 D. Dark LaTeX vs. Light LaTeX 题解

ICPC23沈阳区域赛 D. Dark LaTeX vs. Light LaTeX 题解

时间:2024-11-08 13:58:20浏览次数:1  
标签:LaTeX 前缀 int 题解 sum vs str sim

D. Dark LaTeX vs. Light LaTeX

The 2023 ICPC Asia Shenyang Regional Contest (The 2nd Universal Cup. Stage 13: Shenyang)

给两个字符串 \(s,t\),长度分别为 \(n,m\),现在分别取 \(s,t\) 的子串 \(s',t'\),合成一个新的长度为偶数的字符串 \(str=s'+t'\),记 \(str\) 的长度为 \(2k\),问有多少种取字符串的方法使得 \(str_{1\sim k}=str_{k+1,2k}\)。

sample

input:			output:
abab			8
ab

\((1,1,1,1)(1,1,1,1), (1,2,1,2)(1,2,1,2), (1,3,2,2)(1,3,2,2), (2,2,2,2)(2,2,2,2)\)

\(n,m\leq 5\times 10^3\)

不妨先假设 \(str\) 至少半部分都属于 \(s\) 串,即 \(str_{1\sim p}=s',p\in[k,2k-1]\)。如果 \(str\) 串只有前小半部分属于 \(s\) 串,即 \(str_{1\sim p}=s',p\in[1,k-1]\),那么可以将两个串先前后翻转,再将 \(s\) 串作为 \(t\) 串,\(t\) 串作为 \(s\) 串,执行前多半部分属于 \(s\) 串的操作;同时会发现 \(str_{1\sim k}=s'=str_{k+1,2k}=t'\) 的情况会考虑两次,可以单独减去(具体实现就不讲了)。

懒得画多个图了,所以可能思维比较跳跃,将就着看了

由于 \(s'\) 占据了整个 \(str_{1\sim k}\) 和 \(str_{k+1\sim 2k}\) 的一个前缀,这个前缀必然要和 \(str_{1\sim k}\) 的一个前缀完全匹配。而 \(t'\) 显然要与 \(str_{1\sim k}\) 的一个后缀能够匹配,这个后缀存在于 \(s\) 中,同时需要 \(匹配前缀长+ 匹配后缀长\geq k\) ,这样才能拼接合法。至此我们明确了合法的构造方法。

记 \(f_{i,j}\) 为 \(s_{i\sim n}\) 和 \(s_{j\sim n}\) 的最长公共前缀,\(g_{i,j}\) 为 \(s_{1\sim i}\) 和 \(t_{1,j}\) 的最长公共后缀,我们可以通过 \(O(n^2)\) DP预处理出两者。

\[f_{i,j}=f_{i+1,j+1}+[s_i=s_j] \]

\[g_{i,j}=g_{i-1,j-1}+[s_i=t_j] \]

直接枚举 \(s\) 的一个子串 \(s_{i\sim j}\) 作为 \(str_{1\sim k}\),\(f_{i,j+1}\) 图中蓝色波浪的长度(即 \(k=j-i+1\)),他限制了 \(t'\) 串与 \(str_{1,k}=s_{i,j}\) 匹配的最小长度。同时我们让 \(t_{1\sim p}\) 与 \(str_{1\sim k}\) 进行后缀的匹配,\(g_{j,p}\) 为图中绿串的长度。能够成功拼接的方案数就是 \(\min(f_{i,j+1}+g_{j,p}-k+1,f_{i,j+1}+1)\)。

这样枚举 \(i,j,p\),我们就得到了一个 \(O(n^3)\) 的算法。考虑进行优化。

可以先枚举 \(j\),枚举 \(p\) 将 \(g_{j,p}\) 放入“数据结构”中,再在枚举 \(i\) 的时候 \(O(1)\) 地统计每个所有 \(p\) 的答案。这个问题只需要维护两个前缀和即可

\[s_p=\sum_{i=1}^{m}g_{j,p}\\ \]

\[b_p=\sum_{i=1}^{m}[g_{j,p}>0] \]

每个 \(i\) 的答案

\[\begin{align} ans&=\sum_{p=1}^{m}\min(f_{i,j+1}+g_{j,p}-k+1,f_{i,j+1}+1)[g_{j,p}\geq k-f_{i,j+1}]\\ &=\sum_{p=1}^{m}(f_{i,j+1}+1)[g_{j,p}>k]+\sum_{p=1}^{m}(f_{i,j+1}+g_{j,p}-k+1)[k\geq g_{j,p}\geq k-f_{i,j+1}]\\ &=(b_{m}-b_{k})\times (f_{i,j+1}+1)+(b_k-b_{k-{f_{i,j+1}-1}})\times (f_{i,j+1}-k+1)+(s_k-s_{k-f_{i,j+1}-1}) \end{align} \]

具体实现见代码吧,快下课了

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=5003;
char s[N],t[N],z[N];
int n,m,f[N][N],g[N][N];
ll ans=0,sumn[N],suml[N];
inline void solve(int flag){
	memset(f,0,sizeof(f));
	memset(g,0,sizeof(g));
	memset(sumn,0,sizeof(sumn));
	memset(suml,0,sizeof(suml));
	for(int i=n;i>=1;--i){
		for(int j=n;j>=1;--j){
			if(s[i]==s[j])
				f[i][j]=f[i+1][j+1]+1;
		}
	}
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j)
			if(s[i]==t[j])
				g[i][j]=g[i-1][j-1]+1;
	}
	for(int i=1;i<=n;++i){
		for(int j=0;j<=m;++j)
			sumn[j]=suml[j]=0;
		for(int j=1;j<=m;++j){
			if(!g[i][j])continue;
			++sumn[g[i][j]];
			suml[g[i][j]]+=g[i][j];
		}
		for(int j=1;j<=m;++j){
			sumn[j]+=sumn[j-1];
			suml[j]+=suml[j-1];
		}
		for(int j=1;j<=i;++j){
			int len=f[i+1][j],dis=i+1-j;
			ll L=max(1,dis-len),R=dis-flag;
			if(L>R||R>m)continue;
			ans+=suml[R]-suml[L-1]-(sumn[R]-sumn[L-1])*(L-1);
			ans+=(sumn[m]-sumn[R])*(R-L+1);
		}
	}
}

int main(){
	scanf("%s%s",s+1,t+1);
	n=strlen(s+1),m=strlen(t+1);
	solve(0);
	for(int i=1;i<=n/2;++i)swap(s[i],s[n-i+1]);
	for(int i=1;i<=m/2;++i)swap(t[i],t[m-i+1]);
	swap(s,t);swap(n,m);
	solve(1);
	printf("%lld\n",ans);
	return 0;
}

标签:LaTeX,前缀,int,题解,sum,vs,str,sim
From: https://www.cnblogs.com/BigSmall-En/p/18534930

相关文章

  • 题解:P11249 [GESP202409 七级] 小杨寻宝
    题目显然等价于问所有宝箱是否在一条链上。稍微转化一下题意,即我们现在要找到一条链,使得这条链上有宝物的节点数量尽可能多。想到这里我们发现这个和树的直径比较相似,那么我们直接大胆将深度定义为从根到这个节点上有宝箱节点的数量,然后做一遍树的直径。最后判断直径长度是否等......
  • VS 2022 不支持 .NET Framework 4.5 项目解决办法(Visual Studio 2022)
    VS2022不支持.NETFramework4.5项目解决办法(VisualStudio2022) 概述最近C#开发工具VisualStudio升级到了2022,打开速度快了很多,开发体验也舒服很多。只是使用过程中遇到了一个比较尴尬的问题:默认VisualStudio2022不再支持安装.NETFramework4.5组件,如下图所......
  • 题解:3254. 长度为 K 的子数组的能量值
    Problem:3254.长度为K的子数组的能量值I题解:3254.长度为K的子数组的能量值给定一个数组nums和一个整数k,我们需要找出所有长度为k的子数组的“能量值”。根据题意:如果子数组是连续递增的,能量值等于子数组中的最大元素。否则,能量值为-1。以下是两种不同......
  • CF 1365 题解
    CF1365题解AMatrixGame注意到每次操作都相当于会损失一行和一列,那么最多进行可用行列较少的那一个的轮数.判断奇偶性即可,BTroubleSort手玩发现,不管一个属性的元素集合内部多么无序,都可以借助一个其它属性的元素达到有序.归纳证明特别简单.因此,一个序列可以......
  • P5479 [BJOI2015] 隐身术 题解
    题目传送门前置知识后缀数组简介|字符串哈希|二分解法考虑分别计算出编辑距离恰好等于\(k_{0}\in[0,k]\)的答案。观察在编辑距离的存在下,长度差至多为\(k\)。考虑设\(f_{i,j}\)表示最大的\(x\)使得\(s_{1\simx}\)和\(t_{1\simx+j}\)可以在\(i\)次编......
  • computed 计算属性 vs methods 方法区别
    computed计算属性:更侧重于业务作用:封装了一段对于数据的处理,求得一个结果,语法:①写在computed配置项中②作为属性,直接使用→this.计算属性{{计算属性}}methods方法:更侧重于业务作用:给实例提供一个方法,调用以处理业务逻辑语法:①写在methods配置项......
  • P7984 [USACO21DEC] Tickets P 题解
    题目传送门前置知识线段树优化建图|最短路解法考虑对票建虚点,从\(c_{i}\)向\(i+n\)连一条权值为\(p_{i}\)的边,然后从\(i+n\)向\([a_{i},b_{i}]\)连一条权值为\(0\)的边。建出反图后\(1\toi\)和\(n\toi\)的路径集合会有重复统计的部分,不妨以\(dis_{1,i......
  • 快速上手Docker部署Flask项目 附常见问题解决
    一、准备Flask项目1.项目结构有一个app.py文件作为主应用程序入口,内容示例:fromflaskimportFlaskapp=Flask(__name__)@app.route('/')defhello_world():return'Hello,World!'if__name__=='__main__':app.run(host='0.0.0.0&#......
  • P9192 [USACO23OPEN] Pareidolia P 题解
    P9192[USACO23OPEN]PareidoliaP题解首先自然考虑不带修的情况。考虑问题的本质就是求序列中尽量短的bessie序列个数。对于尽量短的理解是对于bessiebessie序列,不考虑其由\(1,8\sim12\)构成的序列,只考虑\(1\sim6,7\sim12\)组成的序列。于是考虑dp:设\(dp_{i......
  • CF1956F Nene and the Passing Game 题解
    处理很妙的题,部分细节请教了未来姚班zyl和LYH_cpp,在此鸣谢。首先考虑把题目给的式子进行转化,设\(i<j\),那么\(i\)和\(j\)能传球当且仅当\(l_i+l_j\lej-i\ler_i+r_j\)。移项并拆开得到,\(i+l_i\lej-l_i\)且\(i+r_i\gej-r_j\),如果画到数轴上的话......