Good Bye 2015 D. New Year and Ancient Prophecy(dp+lcp)

D. New Year and Ancient Prophecy
time limit per test
2.5 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Limak is a little polar bear. In the snow he found a scroll with the ancient prophecy. Limak doesn't know any ancient languages and thus is unable to understand the prophecy. But he knows digits!

One fragment of the prophecy is a sequence of n digits. The first digit isn't zero. Limak thinks that it's a list of some special years. It's hard to see any commas or spaces, so maybe ancient people didn't use them. Now Limak wonders what years are listed there.

Limak assumes three things:

  • Years are listed in the strictly increasing order;
  • Every year is a positive integer number;
  • There are no leading zeros.

Limak is going to consider all possible ways to split a sequence into numbers (years), satisfying the conditions above. He will do it without any help. However, he asked you to tell him the number of ways to do so. Since this number may be very large, you are only asked to calculate it modulo 109 + 7.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 5000) — the number of digits.

The second line contains a string of digits and has length equal to n. It's guaranteed that the first digit is not '0'.

Output

Print the number of ways to correctly split the given sequence modulo 109 + 7.

Examples
Input
6
123434
Output
8
Input
8
20152016
Output
4
Note

In the first sample there are 8 ways to split the sequence:

  • "123434" = "123434" (maybe the given sequence is just one big number)
  • "123434" = "1" + "23434"
  • "123434" = "12" + "3434"
  • "123434" = "123" + "434"
  • "123434" = "1" + "23" + "434"
  • "123434" = "1" + "2" + "3434"
  • "123434" = "1" + "2" + "3" + "434"
  • "123434" = "1" + "2" + "3" + "4" + "34"

Note that we don't count a split "123434" = "12" + "34" + "34" because numbers have to be strictly increasing.

In the second sample there are 4 ways:

  • "20152016" = "20152016"
  • "20152016" = "20" + "152016"
  • "20152016" = "201" + "52016"
  • "20152016" = "2015" + "2016"

【题解参考】http://www.cnblogs.com/hxer/p/5185137.html

【题意】给一个长度为n(1<= n <= 5000)的只含有数字的字符串,字符串首位不为’0’,将字符串分割成数值严格递增的子串;并且每一个子串不能以0开头;这样的分割方式有多少种?

【解题方法&&思路】首先,我们知道要解决这个问题面临着一个最困难的问题就是如何比较两个字串的大小?这里用了lcp这一方法:lcp-->LCP(longest common prefix)使用数组lcp(a,b)表示以a,b开头的子串前缀相同字符的长度;初始化要为-1,不能为0。解决了这个问题,接下来就是dp状态怎么表示了,容易想到dp[l][len]表示起点为l,字串长度为len的方案数。那么转移就比较显然了。dp[l][len] += dp[l+len][len]?dp[l+len][len+1],那么?就是通过lcp来确定字串的大小顺序就好啦。这里记忆化搜索比较好写,但是递推的效率应该高一些。

【AC 代码】

//
//Created by just_sort 2016/9/15 20:05
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 5005;
const int mod = 1e9+7;
int n,lcp[maxn][maxn],dp[maxn][maxn];
char s[maxn];
int Lcp(int a,int b)
{
    if(a>=n || b>=n) return 0;
    int &ret = lcp[a][b];
    if(~ret) return ret;
    ret = 0;
    if(s[a]==s[b]){
        ret = Lcp(a+1,b+1)+1;
    }
    return ret;
}
int f(int l,int len)
{
    if(s[l]=='0') return 0;
    if(l+len>n)   return 0;
    if(l+len==n)  return 1;
    int &ret = dp[l][len];
    if(~ret) return ret;
    ret = 0;
    ret = f(l,len+1);//先求解子结构
    if(l+len<n){
        int a = Lcp(l,l+len);
        ret += (a<len && s[l+a]<s[l+len+a])?f(l+len,len):f(l+len,len+1);
        if(ret>=mod) ret -= mod;
    }
    return ret;
}
int main()
{
    memset(lcp,-1,sizeof(lcp));
    memset(dp,-1,sizeof(dp));
    scanf("%d",&n);
    scanf("%s",s);
    printf("%d\n",f(0,1));
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值