描述
题解
这个题的 dp 思维很简单,设 dp[i][j] 表示前 i 个字符分成 j 份的最优解,不过对于任意区间 [i,j] 的单词数就是一个问题了,一开始没有想通这里怎么搞,所以就否定了这种 dp 思路,恐怕搞不定它,后来发现数据如此之小,单词不超过 6 个,字符串长度不超过 200,简直就是为暴力而生,于是暴力一发,求出任意区间的 val[][],dp 搞搞竟然 AC 了,太诧异了……做习惯了 51Nod,总是不由自主的否定了暴力的思维,实在是不应该啊!
代码
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 222;
const int MAXM = 9;
int P, K, n;
int val[MAXN][MAXN];
int dp[MAXN][MAXN];
int vis[MAXN];
char s[MAXN];
char w[MAXM][MAXN];
int main()
{
scanf("%d%d\n", &P, &K);
int cnt = 0;
for (int i = 1; i <= P; i++)
{
for (int j = 0; j < 20; j++)
{
scanf("%c", &s[++cnt]);
}
getchar();
}
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%s", w[i]);
}
for (int i = 1; i <= cnt; i++)
{
for (int j = i; j <= cnt; j++)
{
memset(vis, 0, sizeof(vis));
for (int k = 1; k <= n; k++)
{
int len = (int)strlen(w[k]);
for (int o = i; o <= j - len + 1; o++)
{
if (vis[o])
{
continue;
}
bool flag = 1;
for (int p = 0; p < len; p++)
{
if (s[o + p] != w[k][p])
{
flag = 0;
break;
}
}
if (flag)
{
val[i][j]++;
vis[o] = 1;
}
}
}
}
}
for (int k = 1; k <= K; k++)
{
for (int i = 1; i <= cnt; i++)
{
for (int j = k - 1; j <= i - 1; j++)
{
dp[i][k] = max(dp[i][k], dp[j][k - 1] + val[j + 1][i]);
}
}
}
// cout << s + 1 << '\n';
printf("%d\n", dp[cnt][K]);
return 0;
}