CF611D lcp+dp

本篇博客只是留个辣鸡的自己标记一下,误入的同学请出门左转博客

https://blog.csdn.net/loy_184548/article/details/50865777

代码神马的也是复制啊

#include <bits/stdc++.h>
#define mst(a) memset(a,0,sizeof (a))
#define FOR(i,n) for (int i = 0; i < n; i++)
#define INF 1e9
#define mod 1000000007
#define eps 1e-10
using namespace std;

typedef long long ll;
int n;
string s;
int lcp[5005][5005];
int dp[5005][5005];  //前i长度,最后一个数长度为j的方法数 
int sum[5005][5005];
void getLcp() //最长公共前缀lcp
{
    for (int i = n; i > 0; i--)
    {
        for (int j = n; j > i; j--)
        {
            if (s[i] == s[j]) lcp[i][j] = lcp[i + 1][j + 1] + 1;
            else lcp[i][j] = 0;
        }
    }
} 
bool check(int a,int b)
{
    char ret1 = s[a+lcp[a][b]];
    char ret2 = s[b+lcp[a][b]];
    if (ret1 < ret2) return true;  //满足条件返回1 
    else return false;
}
void solve()
{
    for (int i = 0; i <= n; i++) sum[0][i] = 1;   //初始化
    for (int i = 1 ; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            /*在前面基础上加上一段j长度*/ 
            int len = i - j + 1;  //j串的开头位置 
            if (s[len] == '0') continue;   //处理前缀0

            /*1.处理前面最后一段比j短的情况(即数字一定比j小)*/ 
            dp[i][j] = sum[len - 1][j - 1]; //sum[i][j]表示前i长度,最后一个长度为小于j的方法总数

            /*2.处理前面最后一段和j相等的情况*/
            int tmp = len - j;
            if (tmp < 1) continue;  //前面总长度没有j长
            if (check(tmp,len) && lcp[tmp][len] < j)  //判断j这段是否满足条件 
            {
                dp[i][j] = (dp[i][j] + dp[len - 1][j]) % mod;
            } 
        }
        for (int j = 1; j <= n; j++)
        {
            sum[i][j] = (sum[i][j - 1] + dp[i][j]) % mod; 
        }
    } 
}
int main(){ 
    cin >> n >> s;
    s = " " + s;
    /*求出最长公共前缀lcp,用于快速比较两个数的大小 
        如果lcp[a][b] >= len,说明两个数字相等
        否则比较s[a+lcp[a][b]]和s[b+lcp[a][b]]即可 
    */ 
    getLcp();   //最长公共前缀lcp
    solve();
    ll ans = 0; 
    for (int i = 1; i <= n; i++)
    {
        ans = (ans + dp[n][i]) % mod;
    }
    cout << ans << endl;
    return 0;
}

 

posted @ 2018-10-09 16:22  ASDIC减除  阅读(338)  评论(0编辑  收藏  举报