L3-020 至多删三个字符 (30 分)
给定一个全部由小写英文字母组成的字符串,允许你至多删掉其中 3 个字符,结果可能有多少种不同的字符串?
输入格式:
输入在一行中给出全部由小写英文字母组成的、长度在区间 [4, 1] 内的字符串。
输出格式:
在一行中输出至多删掉其中 3 个字符后不同字符串的个数。
输入样例:
ababcc
输出样例:
25
提示:
删掉 0 个字符得到 "ababcc"。
删掉 1 个字符得到 "babcc", "aabcc", "abbcc", "abacc" 和 "ababc"。
删掉 2 个字符得到 "abcc", "bbcc", "bacc", "babc", "aacc", "aabc", "abbc", "abac" 和 "abab"。
删掉 3 个字符得到 "abc", "bcc", "acc", "bbc", "bac", "bab", "aac", "aab", "abb" 和 "aba"。
显然这道题用动态规划状态转移,无奈动态规划学的很渣,重复情况需要考虑。
最基本的是到了第i位,删或者不删,不删表示删除个数不变,删了表示删除个数加1,以第i - 1个字符的情况为基础,创建数组dp[MAX][4],dp[i][j]表示到了第i(i >= 1)个字符,已经删了j个字符有多少字符串,我们要计算dp[i][j],考虑两种情况删或者不删,删的话,就是dp[i - 1][j - 1],表示在i - 1时删了j - 1,到了i后又删了一个一共删了j个,不删的话就是dp[i - 1][j],表示在第i - 1时就删了j个,第i个不删所以一共还是删了j个,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
但是肯定会有重复的情况,我们只需要保证,到了位置i我们清除掉他的重复情况,这样在计算后面情况时就不用考虑太多因为前面的都是没有重复的情况,要去掉重复的,只需要以前面的为基础即可。
比如 abcdedc,显然如果删除了de和ed是一样的,都生成abcc,我们从前往后计算,到了位置6(下标从1开始),我们按照上面的式子算出了它的情况,其中dp[6][2]会包含删除ed的情况,dp[6][3]也包含删除ed但不是ded的情况即在123位置中再选一个删除,对于dp[6][2]我们需要减去什么,显然现在是删除了两个字符,删除de的情况其实就是abc一个都不删除的情况,即dp[3][0],对于dp[6][3]删除了三个字符,包含ed且不是ded也就是要减去123位置有一个字符被删除了的情况,即dp[3][1],所以对于dp[i][j],我们需要记录s[i]上一次出现的位置d d = pos[s[i]],如果d不为0,而且j - (i - d) >= 0(i - d表示什么,比如上例中ed是两个字符,i - d = 2,j减去它表示到了位置d - 1,删了几个字符),那么就dp[i][j] -= dp[d - 1][j - i + d].
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 1000000
using namespace std;
typedef long long ll;
char s[MAX + ];
ll dp[MAX + ][];
int pos[];
int main() {
scanf("%s",s + );
dp[][] = ;
int len = strlen(s + );
for(int i = ;i <= len;i ++) {
dp[i][] = ;
int d = pos[s[i] - 'a'];
pos[s[i] - 'a'] = i;
for(int j = ;j < ;j ++) {
dp[i][j] += dp[i - ][j - ] + dp[i - ][j];
if(d && j - i + d >= ) {
dp[i][j] -= dp[d - ][j - i + d];
}
}
}
printf("%lld",dp[len][] + dp[len][] + dp[len][] + dp[len][]);
}
L3-020 至多删三个字符 (30 分)的更多相关文章
- L3-020 至多删三个字符 (30 分)(DP)
题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805046946938880 学习地址: 2018CCCC-L3 ...
- pta l3-20(至多删三个字符)
题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805046946938880 题意:给定一个长度<=106 ...
- L3-020 至多删三个字符 (30 分) 线性dp
给定一个全部由小写英文字母组成的字符串,允许你至多删掉其中 3 个字符,结果可能有多少种不同的字符串? 输入格式: 输入在一行中给出全部由小写英文字母组成的.长度在区间 [4, 1] 内的字符串. 输 ...
- PAT L3-020 至多删三个字符
https://pintia.cn/problem-sets/994805046380707840/problems/994805046946938880 给定一个全部由小写英文字母组成的字符串,允许 ...
- PTA L3-020 至多删三个字符 (序列dp/序列自动机)
给定一个全部由小写英文字母组成的字符串,允许你至多删掉其中 3 个字符,结果可能有多少种不同的字符串? 输入格式: 输入在一行中给出全部由小写英文字母组成的.长度在区间 [4, 1] 内的字符串. 输 ...
- PTA 团体程序设计天梯赛 L3-020 至多删三个字符
$f[i][j]$表示到第$i$个字符,已经删去了$j$个字符的方案数. 显然的转移: $f[i][j] = f[i - 1][j] + f[i - 1][j - 1]$ 但是这样会有重复,我们考虑什 ...
- [leetcode]680. Valid Palindrome II有效回文II(可至多删一原字符)
Given a non-empty string s, you may delete at most one character. Judge whether you can make it a pa ...
- PTA 最多删除3个字符(DP) - 30分
给定一个全部由小写英文字母组成的字符串,允许你至多删掉其中 3 个字符,结果可能有多少种不同的字符串? 输入格式: 输入在一行中给出全部由小写英文字母组成的.长度在区间 [4, 1] 内的字符串. 输 ...
- windows自带记事本导致文本文件(UTF-8编码)开头三个字符乱码问题
在windows平台下,使用系统的记事本以UTF-8编码格式存储了一个文本文件,但是由于Microsoft开发记事本的团队使用了一个非常怪异的行为来保存UTF-8编码的文件,它们自作聪明地在每个文件开 ...
随机推荐
- Shell需注意的语法问题
1.文件头声明别漏掉#和! #!/bin/bash 2.赋值语句①=号两端不能有空格(判断语句=号两端必须有空格)②使用变量必须使用符号$ var1=valecho $var1 3.if语句写错下面任 ...
- LeetCode--141--环形链表
问题描述: 给定一个链表,判断链表中是否有环. 思路:用快的指针追慢的指针,只要有圈,一定能追上. 错误: class Solution(object): def hasCycle(self, hea ...
- DOM文档对象模型
- windows下线程间的通信方式
1.事件: (在信息交换函数中将控件的值与控件id进行绑定,这样我们就可以更新或者获取控件的值) void CMy0722ThreadTalkingDlg::DoDataExchange(CDataE ...
- 用了皮肤控件之后,报错:容量超出了最大容量 参数名:capacity
用了皮肤控件之后,报错:容量超出了最大容量 参数名:capacity MessageBox.show()错误!!容量超出了最大容量.参数名: capacity 解决方案: 设置 skin.SkinDi ...
- Executors类的newFixedThreadPool, newCachedThreadPool, newScheduledThreadPool
Executors 类对 ThreadPoolExecutor 的构造函数进行了封装,使用该类可方便地创建线程池. 1. newFixedThreadPool public static Execut ...
- elment-ui table组件 -- 远程筛选排序
elment-ui table组件 -- 远程筛选排序 基于 elment-ui table组件 开发,主要请求后台实现筛选 排序的功能. 需求 排序 筛选 是对后台整个数据进行操作,而不是对当前页面 ...
- 共享内存创建shmget控制操作shmat,shmctl
1.共享内存的数据结构 共享内存就是分配一块能被其他进程访问的内存.每个共享内存段在内核中维护着一个内部结构: struct shmid_ds { struct ipc_perm shm_perm; ...
- spring cloud 学习(二)关于 Eureka 的学习笔记
关于 Eureka 的学习笔记 个人博客地址 : https://zggdczfr.cn/ ,欢迎光临~ 前言 Eureka是Netflix开发的服务发现组件,本身是一个基于REST的服务.Sprin ...
- 查看dll导出函数的方法
1.使用VS自带工具: (1)进入VS开发环境,然后Tools -> Visual studio 2015 Command Prompt,打开兼容工具命令提示符, (2)cd到dll所在目录,输 ...