题意:
给你一个长度为n的仅包括小写字母的字符串,每个小写字母能在一个长度不超过a[i](i是小写字母序号如a为0)的子串中。
问:
1.有多少种分隔方法
2.所有分割方法中最长的子串有多长
3.所有分隔方法中最少能字字符串分隔成几段
题解:
设dp[i][0]为前i个字符包括的分隔方法,dp[i][1]为前i个字符包括的所有分隔方法中最少能分隔成几段,ans为所有分隔方法中最长的子串长度
则对于第k个字符串有:
for(int i=k;i>0;i--) {
mn = min(mn, a[s[i]-'a']);
if(mn >= k-i+1) {
dp[k][0] = (dp[k][0] + dp[i-1][0])%mod;
ans = max(ans, k-i+1);
dp[k][1] = min(dp[k][1], dp[i-1][1] + 1);
}
else
break;
}
因为第k个字符串如果将自己看成一个子串则分隔方法就要加上dp[k][0] += dp[k-1][0],如果第k个字符能够(即min(a[s[k]-‘a’], a[s[k-1]-'a']) >= 2)和第k-1个字符看成一个长度为2的子串的话dp[k][0] += dp[k-2][0] ,以此类推一直到不能够和第i个字符组成子串为止。
ans在dp过程中不断更新即可
与dp[k][0]原理相同,如果字符能够和第i个字符组成子串的话dp[k][1] = min(dp[k][1], dp[i-1][1] + 1)
#include<iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include<stdlib.h>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<time.h>
using namespace std;
#define MAX_N 1005
#define inf 0x7fffffff
#define LL long long
#define ull unsigned long long
#define mod 1000000007
LL INF=9e18;
int n;
char s[MAX_N];
int dp[MAX_N][2];
int a[30];
int ans = 0;
void cal(int k)
{
int mn = inf;
dp[k][1] = inf;
for(int i=k;i>0;i--) {
mn = min(mn, a[s[i]-'a']);
if(mn >= k-i+1) {
dp[k][0] = (dp[k][0] + dp[i-1][0])%mod;
ans = max(ans, k-i+1);
dp[k][1] = min(dp[k][1], dp[i-1][1] + 1);
}
else
break;
}
}
int main()
{
cin >> n;
cin >> s+1;
for(int i=0;i<26;i++)
cin >> a[i];
dp[0][0] = 1;
for(int i=1;i<=n;i++) {
cal(i);
}
cout << dp[n][0] << endl;
cout << ans << endl;
cout << dp[n][1] << endl;
}