动态规划:其中f[i][j]表示字符序列前i个字符分成j份时,单词出现的次数,sum[i][j]表示字符序列中从第i个字符到第j个字符之间出现词典中的单词的总个数。状态转移方程如下:
f[i][j] = max{f[u][j-1], sum[u+1][i]} 其中j-2 <= u <= i-1
sum[i][j] = sum[i+1][j] + temp 其中temp = (从字符串第i个字符开头,能匹配上词典中的任意一个单词 ? 1 : 0)
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int p,k,n;
string c;
string w[7];
int f[210][50],sum[210][210];
int makesum (int a, int b){
if(sum[a][b]!=-1) return sum[a][b];
int temp = 0;
for(int i = 0; i < n; i++){
if(w[i].length()<=b-a+1 && w[i]==c.substr(a,w[i].length())) {
temp = 1;
break;
}
}
sum[a][b] = temp + (a<b ? makesum(a+1, b) : 0);
return sum[a][b];
}
int main(int argc, const char * argv[])
{
int t;
scanf("%d", &t);
while (t > 0) {
t--;
scanf("%d %d", &p, &k);
for(int i = 0; i < p; i++){
string temp;
cin >> temp;
c += temp;
}
scanf("%d", &n);
for(int i = 0; i < n; i++){
cin >> w[i];
}
memset(f, 0, sizeof(f));
memset(sum, -1, sizeof(sum));
for(int i = 0; i < c.length(); i++){
f[i][1] = makesum(0, i);
}
for(int i = 2; i <= k; i++){
for(int j = i-1; j < c.length(); j++){
int tempmax = 0;
for(int u = i-2; u < j; u++){
tempmax = (tempmax < (f[u][i-1]+makesum(u+1, j)) ? f[u][i-1]+makesum(u+1, j) : tempmax);
}
f[j][i] = tempmax;
}
}
printf("%d\n", f[c.length()-1][k]);
}
}