ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

cf611 D. New Year and Ancient Prophecy(dp+LCP)

2022-02-28 01:31:45  阅读:171  来源: 互联网

标签:Ancient LCP lcp int r2 cf611 l1 l2 r1


题意:

把一个n位整数切成若干段,得到若干个整数。要求每个数都不为0,每个数都没有前缀0,且前一个数严格小于后一个数。问切割数方案取模。

\(n\le 5000\)

思路:

\(O(n^2)\) 的dp,\(f(l,r)\) 表示最后一段是 \([l,r]\) 的方案数,则答案是 \(\sum\limits _i f(i,n)\)

状态转移:若(作为一个整数的)\(a[l,i]<a[i+1,r]\) ,则 \(f(i+1,r)+=f(l,i)\)

双指针,\(l\) 从 \(i\) 开始往左走,\(r\) 从 \(i+1\) 开始走到 \(a[l,i]<a[i+1,r]\) 的第一个位置,那么 \(f(i+1,r\sim n)\) 都能被更新,也就是一个后缀被更新。开个差分数组处理区间加。

注意不能有前导零,且要初始化 \(f(1,1\sim n)=1\)

上面的dp不难想到,但是一般比较两个子串是 \(O(n)\) 的,需要加速。一个方法是 $ O(n^2)$ 预处理 \(lcp(i,j)\) 表示以 \(a_i,a_j\) 开始的最长公共子串的长度。

const int N = 5005, MOD = 1e9 + 7;
int n, lcp[N][N], f[N][N], b[N];
char a[N];
void init()
{
    for(int i = n; i; i--)
        for(int j = n; j; j--)
            if(a[i] == a[j])
                lcp[i][j] = lcp[i+1][j+1] + 1;
}
bool ok(int l1, int r1, int l2, int r2)
{ //前一个是不是比后一个小
    if(r1-l1 != r2-l2) return r1-l1 < r2-l2;
    int p = lcp[l1][l2];
    if(p >= r1 - l1 + 1) return 0;
    return a[l1+p] < a[l2+p];
}
signed main()
{
    cin >> n >> a + 1;
    init();

    for(int i = 1;  i <= n; i++) f[1][i] = 1;
    for(int i = 1; i < n; i++)
    {
        if(a[i+1] == '0') continue; //不能有前导零
        memset(b, 0, sizeof b);
        int r = i + 1;
        for(int l = i; l; l--)
        {
            while(r <= n && !ok(l,i,i+1,r)) r++;
            if(r <= n) (b[r] += f[l][i]) %= MOD;
        }
        for(int j = i + 1; j <= n; j++)
            (b[j] += b[j-1]) %= MOD, (f[i+1][j] += b[j]) %= MOD;
    }

    int ans = 0;
    for(int i = 1; i <= n; i++) (ans += f[i][n]) %= MOD;
    cout << ans;
}

标签:Ancient,LCP,lcp,int,r2,cf611,l1,l2,r1
来源: https://www.cnblogs.com/wushansinger/p/15944053.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有