题意
给出一个字符串 和每个字符的限制数量ai 让我们随意的切割成多个字符串 使得每一个字符串中的特定字符所在的子串长度len<=ai
求一共有多少个符合题目要求的方案 求其中最长的一个串长度是多少 求其中最少能分成多少个串
长度最大为1000
分析
明显可以用搜索 不过复杂度指数级 计数问题
考虑dp
对于第i个字符 他可以考虑从i-ai+1开始往后到i分割字符 我们这里可以枚举分割的位置
然后记录下来 那么对于第i个字符 我们知道他前面所有字符的分割数量 就可以更新第i个字符的分割方案 假设用dp[i]表示从1到第i个字符的可行分配方案 那么dp[i] +=dp[j]其中合法情况之和 就可以计数出所有情况的可能
code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int mod = 1e9+7;
char a[1010];
int dp[1010],mmin[1010],mmax,res[26];
bool judge(int pos,int l){for(int i=pos-l+1;i<=pos;i++){if(res[a[i]-'a']<l)return 0;}return 1;
}
int main()
{int n;scanf("%d%s",&n,a+1);for(int i=0;i<26;i++)scanf("%d",&res[i]);dp[0]=1;for(int i=1;i<=n;i++){mmin[i] = mod;for(int j=1;j<=i;j++){if(judge(i,j)){//如果符合条件 就把方案数转移到更长的字符下dp[i] = (dp[i]+dp[i-j])%mod;mmin[i] = min(mmin[i],mmin[i-j]+1);//两个dp变量 都要更新 这里就是要把段数一并更新 mmax = max(mmax,j);}}}printf("%d\n%d\n%d\n",dp[n],mmax,mmin[n]);return 0;
}