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

题意就不说了,我们设一个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 900MS

from __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 3200
const 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);
}



猜你喜欢

转载自blog.csdn.net/u013569304/article/details/55045907