Codeforces 766C:Mahmoud and a Message(DP)

时间:2022-02-19 05:57:31

题目链接:http://codeforces.com/problemset/problem/766/C

Codeforces 766C:Mahmoud and a Message(DP)

题意

有一个长度为n的字符串,第二行有26个数字,位置1~26对应为a~z的字母,数值表示该字母不能出现在长度超过该值的子串中。

  • 求有多少种划分该字符串的方法
  • 求该字符串划分成子串后最大的子串的长度
  • 求该字符串划分成满足要求的子串需要至少划分多少次

AC代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <limits.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
#define ll long long
#define ms(a) memset(a,0,sizeof(a))
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
const double E=exp(1);
const int maxn=1e6+10;
const int mod=1e9+7;
using namespace std;
char ch[maxn];
int c[maxn];
int a[maxn];
int dp[4][maxn];
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
int n;
cin>>n;
cin>>ch;
for(int i=0;i<26;i++)
cin>>a[i];
for(int i=0;i<n;i++)
{
c[i]=ch[i]-'a';
}
dp[0][0]=1;//从位置0开始转移
for(int i=1;i<=n;i++)
{
int res=INT_MAX/2;
dp[1][i]=INT_MIN/2;
dp[2][i]=INT_MAX/2;
for(int j=i-1;j>=0;j--)
{
res=min(res,a[c[j]]);
if(res<i-j)
break;
dp[0][i]=(dp[0][i]%mod+dp[0][j]%mod)%mod;
dp[1][i]=max(dp[1][i],max(dp[1][j],i-j));
dp[2][i]=min(dp[2][i],dp[2][j]+1);
}
}
for(int i=0;i<3;i++)
cout<<dp[i][n]<<endl;
return 0;
}