C.Mahmoud and a Message Codeforces Round #396 (Div. 2)(DP)

来源:互联网 发布:华为校招 知乎 编辑:程序博客网 时间:2024/06/06 11:46

题意就不说了,我们设一个dp数组,dp[i]表示长度为i的前缀有多少种符合条件的分割方法,dp[0]设置为1。

那么dp[i]=dp[i-1]+dp[i-2]+...+dp[i-j],j是当前第i个字符和第i-j+1个字符之间所包含字符对应的限制数组(题目中的ai)的最小值。所以在计算的时候,要不断更新j 的值保证符合条件。

O(n^2)的时间复杂度算出dp[n]就是最多方案数。最长子串在dp的过程中更新。借助一个数组lastMatch求分割的最少数量,lastMatch[i]表示以第i个字符开始,最长到lastMatch[i]个字符为一段,最后贪心,O(n)跑一遍求出最少分割数。

先用python写了一遍 TLE ,以为是语言的事,用C++写了一遍还是TLE,才发现是有数据死循环了。最后都过了,python 900MS / C++ 15MS。


#python 900MSfrom __future__ import print_function;n=input();str=raw_input();arr=raw_input().split();arr=map(eval,arr);MOD=1e9+7;dp=[0]*3200;dp[0]=1;lastMatch=[0]*3200;for i in range(len(lastMatch)) :lastMatch[i]=i;maxSubLen=0;for i in range(1,len(str)+1) :j=1;k=arr[ord(str[i-1])-ord('a')];while j<=k and i-j>=0 :maxSubLen=max(j,maxSubLen);dp[i]=(dp[i]+dp[i-j])%MOD;t=i-j-1;lastMatch[t+1]=max(lastMatch[t+1],i-1);t=t if t>0 else 0;k=min(k,arr[ord(str[t])-ord('a')]);j+=1;lastIndex=0;lastStrIndex=len(str)-1;subNum=0;#print(lastMatch[0:10]);while lastIndex<=lastStrIndex :#print('last ',lastIndex);subNum+=1;lastIndex=lastMatch[lastIndex];lastIndex+=1;print(int(dp[len(str)]),maxSubLen,subNum,sep='\n');


//C++ 15MS#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <string>#define maxn 3200const int mod=1e9+7;using namespace std;int dp[maxn],lastMatch[maxn];int arr[30];int main(){    int n;    string str;    cin>>n;    cin>>str;    for(int i=0;i<26;++i)    {        cin>>arr[i];    }    memset(dp,0,sizeof(dp));    dp[0]=1;    for(int i=0;i<str.size();++i)        lastMatch[i]=i;    int maxSubLen=0;    for(int i=1;i<=str.size();++i)    {        int j=1;        int k=arr[str[i-1]-'a'];        while(j<=k && i-j>=0)        {            maxSubLen=max(j,maxSubLen);            dp[i]=(dp[i]+dp[i-j])%mod;            int t=i-j-1;            lastMatch[t+1]=max(lastMatch[t+1],i-1);            t = t > 0 ? t : 0;            k = min(k,arr[str[t]-'a']);            j++;        }    }    int lastIndex=0;    int lastStrIndex=str.size()-1;    int subNum=0;    while(lastIndex<=lastStrIndex)    {        subNum+=1;        lastIndex=lastMatch[lastIndex];        lastIndex++;    }    printf("%d\n%d\n%d\n",dp[str.size()],maxSubLen,subNum);}



0 0
原创粉丝点击