【测试题】sequence
题目
给定一个长度为n(n<=5000)的由['0'..'9']组成的字符串s,v[i,j]表示由字符串s第i到第j位组成的十进制数字。
将它的某一个上升序列定义为:将这个字符串切割成m段不含前导'0'的串,切点分别为k1,k2...km-1,使得v[1,k1]<v[k1+1,k2]<...<v[km-2,km-1]。
请你求出该字符串s的上升序列个数,答案对 10^9+7 取模。
题解
对于这种dp题,如果没有思路,我们可以先从最暴力的搜索开始分析,然后逐步优化
版本1
深搜枚举每一段的起点,搜完后逐段验证。
版本2
发现只要记录当前起点,终点,就可以描述出所有的后续状态,从而实现记忆化搜索。
版本3
把深搜改造成从后往前的dp,开两维记录起点、终点。时间复杂度:$O(n^3)$
版本4
把匹配过程改进,通过dp预处理出所有串的lcp,将匹配过程跳至不相等处。时间复杂度:$O(n^2)$
总结
设发$f[i][j]$表示起点为i,区间长度为j的方案数
那么本段范围为$[i,i+j)$,下一段的终点$>=i+j*2-1$
考虑状态转移:
若当前段比下一段小,则
$f[i][j] = f[i+j][j] + f[i+j][j+1] + ... + f[i+j][n-i]$
否则
$f[i][j] = f[i+j][j+1] + f[i+j][j+2] + ... + f[i+j][n-i]$
但是如果这样枚举会变成$O(n^3)$
我们可以使用后缀和来加速过程。
代码
#include <iostream>
#include <cstdio>
#define N 5001
#define int long long
#define mod (int)1e9+7
using namespace std;
char str[N];
int dp[N][N],n,lcp[N][N];
int compare(int a,int b)
{
int t=min(lcp[a][b],b-a-1);
return str[a+t]<str[b+t];
}
signed main()
{
cin>>n;
scanf("%s",str+1);
for(int i=n;i;i--)//lcp[i][j]表示从str[i,n]和str[j,n]的lcp
{
for(int j=i+1;j<=n;j++)
{
if(str[i]==str[j]) lcp[i][j]=lcp[i+1][j+1]+1;
}
}
for(int i=n;i;i--)//枚举起点
{
if(str[i]=='0') continue;
dp[i][n-i+1]=1;//起点到n划为一块
for(int j=1;j<=n-i;j++)//枚举区间长度,同时也是下一个起点的位置
{
if(compare(i,i+j)) dp[i][j]=dp[i+j][j];//等同于公式1
else dp[i][j]=dp[i+j][j+1];//等同于公式2
}
for(int j=n-i;j;j--)//维护后缀和
{
//cout<<dp[i][j]<<" ";
dp[i][j]+=dp[i][j+1],dp[i][j]%=mod;
}
//cout<<endl;
}
cout<<dp[1][1];
}
【测试题】sequence的更多相关文章
- oracle SEQUENCE 创建, 修改,删除
oracle创建序列化: CREATE SEQUENCE seq_itv_collection INCREMENT BY 1 -- 每次加几个 STA ...
- Oracle数据库自动备份SQL文本:Procedure存储过程,View视图,Function函数,Trigger触发器,Sequence序列号等
功能:备份存储过程,视图,函数触发器,Sequence序列号等准备工作:--1.创建文件夹 :'E:/OracleBackUp/ProcBack';--文本存放的路径--2.执行:create or ...
- DG gap sequence修复一例
环境:Oracle 11.2.0.4 DG 故障现象: 客户在备库告警日志中发现GAP sequence提示信息: Mon Nov 21 09:53:29 2016 Media Recovery Wa ...
- Permutation Sequence
The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- [LeetCode] Sequence Reconstruction 序列重建
Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. Th ...
- [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列
Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...
- [LeetCode] Verify Preorder Sequence in Binary Search Tree 验证二叉搜索树的先序序列
Given an array of numbers, verify whether it is the correct preorder traversal sequence of a binary ...
- [LeetCode] Longest Consecutive Sequence 求最长连续序列
Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...
- [LeetCode] Permutation Sequence 序列排序
The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
随机推荐
- CAS自旋volatile变量
public final int getAndIncrement() { for (;;) { int current = get(); // 取得AtomicInteger里存储的数值 int ne ...
- QT攻略——我在QT中遇到的那些坑
(1)QUdpSocket接收数据 进入槽后,要用这种方式读取,否则可能会导致不发readyRead()信号 .while(udpSocket->bytesAvailable()){ udpSo ...
- day58——模板继承、组件、自定义标签和过滤器、inclusion_tag、静态文件配置、url别名和反向解析、url命名空间
day58 模板相关 模板继承(母版继承) 1. 创建一个xx.html页面(作为母版,其他页面来继承它使用) 2. 在母版中定义block块(可以定义多个,整个页面任意位置) {% block co ...
- 「UNR#1」奇怪的线段树
「UNR#1」奇怪的线段树 一道好题,感觉解法非常自然. 首先我们只需要考虑一次染色最下面被包含的那些区间,因为把无解判掉以后只要染了一个节点,它的祖先也一定被染了.然后发现一次染色最下面的那些区间一 ...
- LOJ2257 SNOI2017 遗失的答案 容斥、高维前缀和
传送门 数字最小公倍数为\(L\)的充分条件是所有数都是\(L\)的约数,而\(10^8\)内最多约数的数的约数也只有\(768\)个.所以我们先暴力找到所有满足是\(L\)的约数.\(G\)的倍数的 ...
- k8s-架构中各个组件介绍
参考链接:https://github.com/opsnull/follow-me-install-kubernetes-cluster kubernetes 概述 1.kubernetes 是什么 ...
- Redis常用配置和命令总结
Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言 ...
- spark存储模块之内存存储--MemeoryStore
MemeoryStore 上一节,我们对BlockManager的主要写入方法做了一个整理,知道了BlockMananger的主要写入逻辑,以及对于块信息的管理.但是,由于spark的整个存储模块是在 ...
- IT之快速提高效率的方法与思考
前言 文章也没什么很高深的问题,大概花个5分钟能看完.是一些大家都知道的道理,作为提醒与总结. 关于提高方面的内容,一般都有个人的方法,但大致都一致.可分为几个步骤. 框架.工具使用相关 使用框架.工 ...
- vue的v-bind详解
前言 v-bind 主要用于属性绑定,比方你的class属性,style属性,value属性,href属性等等,只要是属性,就可以用v-bind指令进行绑定.这篇文章主要介绍了VueJs中的V-bin ...