首页 > 其他分享 >NOIP2015 提高组 子串

NOIP2015 提高组 子串

时间:2024-10-31 18:30:57浏览次数:1  
标签:子串 NOIP2015 匹配 int 提高 205 复杂度 mod

NOIP2015 提高组 子串

感觉是最长公共子序列模型的变式。

容易想到记 \(f[i][j][k]\) 表示 \(A\) 走到了第 \(i\) 位,\(B\) 匹配上了 \(1 \sim j\),目前分成了 \(k\) 段的方案数。

如果强制第 \(i\) 位必须匹配上的话,需要枚举位置 \(p\),满足 \(A[p] = B[j - 1]\)。这样的复杂度是 \(O(n^2m^2)\),无法通过本题。

我们采用类似最长公共子序列的方式,不必强制 \(i\) 必须匹配上,也可以直接从上一个状态继承过来。

具体来说,记 \(f[i][j][k][1/0]\) 表示 \(A\) 走到了第 \(i\) 位,\(B\) 匹配上了 \(1 \sim j\),目前分成了 \(k\) 段,\(a[i]\) 匹配 / 不匹配的方案数。

如果 \(a[i]\) 匹配上了,分段的话,上一位匹没匹配上无所谓,不分段的话,上一位也必须要匹配上,即:

\[f[i][j][k][1] = f[i - 1][j - 1][k - 1][0] + f[i - 1][j - 1][k - 1][1] + f[i - 1][j - 1][k ][1] \]

如果 \(a[i]\) 没匹配上,上一位匹没匹配上无所谓,即:

\[f[i][j][k][0] = f[i - 1][j][k][0] + f[i - 1][j][k][1] \]

答案就是 \(f[n][m][k][0] + f[n][m][k][1]\)。注意有上一位的继承,所以不用枚举谁匹配 \(b[m]\) 了。

时间复杂度 \(O(nm^2)\),而且跑不满,非常快。

算一下空间,\(128MB\) 存不下,把 \(i\) 维给滚掉就可以了。

(今天才发现原来 Luogu 不能 cin >> (a + 1),于是用了 scanf

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
const int mod = 1e9 + 7;
int f[2][205][205][2];
int n, m, s;
char a[1005], b[205];
signed main(){
	scanf("%d %d %d %s %s", &n, &m, &s, a + 1, b + 1);
	F(i, 1, n){
		f[(i - 1) & 1][0][0][0] = 1;
		F(j, 1, m) F(k, 1, s) f[i & 1][j][k][0] = f[i & 1][j][k][1] = 0;
		F(j, 1, min(i, m)){
			F(k, 1, min(j, s)){
				f[i & 1][j][k][0] = (f[(i - 1) & 1][j][k][0] + f[(i - 1) & 1][j][k][1]) % mod;
				if(a[i] == b[j]) 
					f[i & 1][j][k][1] = ((f[(i - 1) & 1][j - 1][k][1]+ f[(i - 1) & 1][j - 1][k - 1][0]) % mod + f[(i - 1) & 1][j - 1][k - 1][1]) % mod;
			}
		}
	}
	printf("%d", (f[n & 1][m][s][0] + f[n & 1][m][s][1]) % mod);
	return fflush(0), 0;
}

本题的关键在于打开思路,不必强制当前位必须匹配,一个小小的定义修改,足以影响复杂度。

标签:子串,NOIP2015,匹配,int,提高,205,复杂度,mod
From: https://www.cnblogs.com/superl61/p/18518625

相关文章

  • LeetCode30.串联所有单词的子串
    题目链接:30.串联所有单词的子串-力扣(LeetCode)1.暴力解法(会超时)由于题目中要判断s中是否有子串符合words,于是可以定义一个hashMap来存储words中的字符串的信息;定义变量len表示words中字符串的数目,strLen表示每个字符串的长度(words中的字符串长度相同);遍历s,每次取出长为len......
  • Meta-Chunking:一种用于提高RAG性能的文本分割技术
    尽管RAG技术在LLMs中具有潜力,但在文本分块方面常常被忽视。文本分块的质量直接影响知识密集型任务的表现。本文提出Meta-Chunking概念,这是一种介于句子和段落之间的文本分割技术,旨在通过逻辑感知来提高文本分割的效率;设计了两种基于LLMs的分块策略:边际采样分块(MarginSam......
  • 在K8S中,有一种情况,公司希望通过保持最低成本来提高效率和技术运营速度,该公司实该如何
    在Kubernetes(K8s)环境中,公司若希望通过保持最低成本来提高效率和技术运营速度,可以采取以下详细策略:一、优化资源配置与利用设置资源请求与限制:为容器设置合理的资源请求(Requests)和限制(Limits),确保它们在不浪费资源的同时获得必要的计算资源。这有助于防止单个容器占用过多的资......
  • 代码生产力提高100倍,Claude-3.5 +Cline 打造超强代码智能体!小白也能开发各种app!
    嘿,各位小伙伴们。今天,带大家走进神奇的AI世界,一起探索强大的工具和技术。最近,Anthropic发布了全新的Claude-3.5-sonnet模型,这可是Claude-3.5-sonnet模型的升级版哦!这款最新的模型在多方面的能力都有了显著提升,尤其是在编程方面。已经完全超越GPT模型,并且其训练数据的截......
  • 如何提高app审核的通过率?
    以下是一些提高App审核通过率的方法:一、了解审核指南仔细阅读苹果和安卓(如GooglePlay)的官方审核指南:熟悉各个平台对App内容、功能、安全性等方面的具体要求。这包括但不限于用户隐私保护、内容规范、性能标准等。对于苹果的AppStore,关注其《AppStore审核指南......
  • 3招提高用户粘性,让你的客户成为终身伙伴
    在数字化时代,企业之间的竞争变得异常激烈,如何在这个快速变化的市场中保持用户的忠诚度,让他们成为你的终身客户,是每个企业都在思考的问题。今天,我们就来探讨三个有效的方法,帮助你提高用户粘性,让客户不仅仅是一次性的交易对象,而是成为你品牌的忠实支持者。 一、充分尊重用户......
  • C++之OpenCV入门到提高002:加载、修改、保存图像
    一、介绍今天是这个系列《C++之Opencv入门到提高》得第二篇文章。今天这个篇文章很简单,只是简单介绍如何使用Opencv加载图像、显示图像、修改图像和保存图像,先给大家一个最直观的感受。但是,不能认为很简单,只是让学习的过程没那么平滑一点,以后的路就好走了。OpenCV具......
  • P1004 NOIP2000 提高组 方格取数
    P1004NOIP2000提高组方格取数-洛谷分析与[[小烈送菜]]算姐妹题了,这个辈分甚至更老一点。如果直接按照题目,从\(A,B\)两点分别出发,那么有个问题就是不确定性,计算的时候不可控因素很多。可以注意到,从\(B\)点往回走到\(A\)点,是和从\(A\)点再走一遍走到\(B\)点是......
  • 如何通过分解问题来提高编程能力?
    通过分解问题来提高编程能力是一种非常有效的方法。分解问题的核心思想是将一个复杂的大问题拆解成更小、更易于管理的子问题,从而更容易解决。这种方法不仅有助于简化问题,还能帮助程序员更好地理解和处理问题。以下是通过分解问题提高编程能力的几个关键步骤:理解问题本质:首先......
  • 【NOIP提高组】均分纸牌
    【NOIP提高组】均分纸牌......