【XSY2564】sequence(字符串+DP)

Description

【题目描述】

给定一个长度为n的由[0..9]组成的字符串sv[i,j]表示由字符串si到第j位组成的十进制数字。

将它的某一个上升序列定义为:将这个字符串切割成m段不含前导0的串,切点分别为k1,k2...km1,使得v[1,k1]<v[k1+1,k2]<...<v[km2+1,km1]

请你求出该字符串s的上升序列个数,答案对109+7取模。


Input

第一行一个整数n,表示字符串长度;

第二行n[0..9]内的字符,表示给出的字符串s


Output

仅一行表示给出字符串s的上升序列个数对109+7取模的值。


SampleInput1

6

123434


SampleOutput1

8


SampleInput2

8

20152016


SampleOutput2

4


Hint

对于30%的数据满足:n<=10

对于100%的数据满足:n<=5000


思路

看到这道题,特征十分明显:求方案数,数值较大(要mod),所以我们果断选择dp

我们设数组dp[i][j]表示第一段以i开头,长度为j(ni+1)的方案数的和

于是,我们最后的答案为dp[1][1],表示第一段以1开头,长度为1n的方案数的和

接着,我们设a[i][j]表示s[i][n](以下s就表示字符串)与s[j][n]的最长公共前缀

显而易见,我们得到s[i][i+a[i][j]1]=s[j][j+a[i][j]1]

则我们在推状转方程时会有三种情况

1. dp[i][ni+1]=1,显而易见,这种情况下这一段直接到n,所以值为1
2. 我们来比较一下两个相邻且长度相等j的字符串所组成的十进制数s[i][i+j1]s[i+j][i+2×j1]的大小

2.1s[i][i+j1]<s[i+j][i+2×j1],那么满足要求,则有

dp[i][j]=dp[i+j][j]

2.2s[i][i+j1]s[i+j][i+2×j1],因为两个字符串长度相等,若后者再往后多一位,还是比前者大,于是有

dp[i][j]=dp[i+j][j+1]

最后,因为要满足dp[i][j]的定义,我们还要将dp[i][j]加上dp[i][j+1],至于为什么,自行理解

现在,推完了状转方程,我们回过头来考虑怎么比较两个数的大小

我们可以比较s[i][i+a[i][i+j]]s[i+j][i+j+a[i][i+j]]的大小,既可以比较两个数大小

但是我们考虑一种情况,若i+a[i][i+j]>i+j1,那么事情就一发不可收拾了,于是我们要取min(j1,a[i][j])


代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n;
char s[5010];
int a[5010][5010];
int dp[5010][5010];
bool check(int i,int j)
{
    int len=min(j-1,a[i][i+j]);
    return s[i+len]<s[i+j+len];
}
int main()
{
    scanf("%d %s",&n,s+1);
    for(int i=n;i>0;i--)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(s[i]==s[j])a[i][j]=a[i+1][j+1]+1;
        }
    }
    for(int i=n;i>0;i--)
    {
        if(s[i]!='0')
        {
            dp[i][n-i+1]=1;
            for(int j=1;j<=n-i;j++)
            {
                if(check(i,j))dp[i][j]=dp[i+j][j];
                else dp[i][j]=dp[i+j][j+1];
            }
            for(int j=n-i;j>0;j--)dp[i][j]=(dp[i][j]+dp[i][j+1])%mod;
        }
    }
    printf("%d\n",dp[1][1]);
}

posted @   ShuraEye  阅读(175)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示