首页 > 其他分享 >CF1714D 题解

CF1714D 题解

时间:2023-04-22 21:14:43浏览次数:27  
标签:pre int 题解 len minx leq mp CF1714D

CF1714D 题解

description

给定黑色文本 \(t\) 和 \(n\) 个字符串 \(s_1,s_2...s_n\). 一次操作可以将 \(t\) 中与 \(s_i\) 相等的子串涂成红色。 一个位置多次涂色后仍是红色。\(s_i\) 可以使用多次。 求将 \(t\) 涂成红色的最小次数,并输出方案。 无解输出-1.

  • \(|t| \leq 100\)
  • 测试数据组数 \(\leq 100\)
  • \(n\leq 10\)
  • \(|s_i| \leq 10\)

solution

线性dp。

\(f_i\) 表示将 \(t\) 的前 \(i\) 个字符涂成红色的最小次数,则

  • \(f_0=0\)

  • \(f_i=\min\{f_j\}+1, p\leq j \leq i\)

其中 \(p\) 是 \(i\) 减去以 \(t_i\) 结尾的能匹配的长度最大的 \(s_k\) 的长度。

特别地,若不存在这样的 \(p\),则 \(f_i=\infty\)

答案即为 \(f_{|t|}\)

为了输出方案,我们记录每个 \(f_i\) 是由哪里转移的并且当前放的是哪一个单词。

由于需要检查字符串是否在 \(\{s\}\) 中,用 std::map 匹配字符串,可将匹配复杂度从 \(\mathcal{O}(n|s_i|)\) 变为 \(\mathcal{O}(|s_i|\log n)\). 代码也更简洁。

code

#include<bits/stdc++.h>

using namespace std;

const int N=1010;

string t,s[110];
int f[N],n,pre[N],len[N];
map<string,bool> mp;
map<string,int> num;

int main(){
	
	ios::sync_with_stdio(false);
	cin.tie(nullptr),cout.tie(nullptr);
	
	int T;
	cin>>T;
	while(T--){
		memset(pre,0,sizeof pre);
		memset(len,0,sizeof len);
		mp.clear();
		num.clear();
		f[0]=0;
		
		cin>>t>>n;
		for(int i=1; i<=n; i++) s[i].clear();
		for(int i=1; i<=n; i++) cin>>s[i];
		for(int i=1; i<=n; i++){
			reverse(s[i].begin(),s[i].end()); //倒着存字符串,方便dp的时候匹配
			mp[s[i]]=true;
			num[s[i]]=i;
		}
		
		f[t.size()+1]=INT_MAX/2; //避免+1爆int
		for(int i=1; i<=t.size(); i++){
			string now;
			f[i]=INT_MAX/2;
			int minx=t.size()+1; //记录从哪里转移
			for(int j=i; j; j--){
				now+=t[j-1];
				if(f[minx]>f[j-1]){
					minx=j-1;
				}
				if(mp.find(now)!=mp.end()){
					if(f[i]>f[minx]+1){
						f[i]=f[minx]+1;
						pre[i]=minx;
						len[i]=now.size();
					}
				}
			}
			
		}
		
		if(f[t.size()]==INT_MAX/2){
			cout<<-1<<'\n';
			continue;
		}
		
		int st=t.size();
		cout<<f[t.size()]<<'\n';
		while(st){
			string q=t.substr(st-len[st],len[st]); //此处记录了每个位置用了多长的字符串来涂色
			reverse(q.begin(),q.end());
			cout<<num[q]<<' '<<st-len[st]+1<<'\n';
			st=pre[st];
		}
		
	}
	
	return 0;
}

标签:pre,int,题解,len,minx,leq,mp,CF1714D
From: https://www.cnblogs.com/FreshOrange/p/17343939.html

相关文章

  • 题解:【CF235D】Graph Game
    题目链接根据期望的线性性,一次操作使得接下来要递归处理\(|G|\)个点,将这些贡献分摊到\(|G|\)个点上,这样我们接下来只需要计算概率。首先考虑如果是树怎么做。操作等价于随机一个排列,顺次删掉排列中的点,并求出删掉当前点之前其所处的连通块的大小。记当前\(x\)为点分治中心......
  • 二叉树经典题解
    目录......
  • winform设置背景图闪屏问题解决
    直接将以下代码复制粘贴到出现闪屏的窗体中即可:#region解决添加背景图片时闪屏的问题protectedoverrideCreateParamsCreateParams{get{CreateParamscp=base.CreateParams;cp.Ex......
  • 暗的连锁 题解
    题目描述Dark是一个无向图,图中有\(n\)个结点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark有\(n-1\)条主要边,并且Dark的任意两个结点之间都存在一条只由主要边构成的路径。另外,Dark还有\(m\)条附加边。你的任务是把Dark斩为不连通的两部分。一开始Dark......
  • ABC298E 题解
    前言题目传送门!更好的阅读体验?题解区的代码都好丑啊,嘲讽。思路对于这种概率题,正常人都能反应到这是dp。所以:\(dp_{t,i,j}\)表示:当前是第\(t\)回合,Tak在\(i\)位置,Aok在\(j\)位置,概率。如果这样设状态的话,转移方程就会非常一眼(刷表):\[dp_{t,\min(i+\texttt{st......
  • [P8766 [蓝桥杯 2021 国 AB] 异或三角]题解
    P8766[蓝桥杯2021国AB]异或三角题目描述分析题目中给出了三个限制首先我们不妨设\(a,b\ltc\),则而由于我们把\(c\)作为了最大值,原题需要有序对\((a,b,c)\)所以\(ans\ast3\)1.\(1\leqa,b,c\leqn\)2.\(a\oplusb\oplusc=0\)3.\(a+b\gtc\)而在枚举过程中,......
  • P1350 车的放置 题解
    一、题目描述:给你一个网格棋盘,a,b,c,d 表示了对应边长度,也就是对应格子数。例如,当a=b=c=d=2时,对应如下面这样一个棋盘:想要在这个棋盘上放 k棋子,也就是这 k 个棋子没有两个在同一行,也没有两个在同一列,问有多少种方案。数据保证 0......
  • [ARC138D] Differ by K bits 题解
    小清新构造题。首先\(K=1\)的情况是trival的,直接格雷码即可。对于\(K>1\),我们发现题目的约束相当于\(\operatorname{popcount}(P_i\oplusP_{(i+1)\bmod2^N})=K\),考虑\(P_i\)的差分序列\(D_i\),那么\(D_i\)一定是一个恰好有\(K\)位\(1\)的二进制数,记\(S=\{i\mid......
  • 团体程序设计天梯赛 L1-064 估值一亿的AI核心代码 题解
    思路L1-064估值一亿的AI核心代码题意有一点不太清晰的,就是原文中的'I',无论是否是单独的,都不能变为小写。如果是单独的'I'再被转化为'you'。这种模拟题就需要每个的分分清清楚楚的,不要都揉到一块儿,容易写错。具体还有些需要注意的在代码里注释着了。代码#include<iostream>......
  • Android Studio Gradle Download 慢/卡问题解决
    build.gradlebuildscript{repositories{//jcenter()//jcenter(){url'http://jcenter.bintray.com/'}maven{url'http://maven.aliyun.com/nexus/content/groups/public/'}maven{url"https://jitpac......