题目大意
给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1< k< =40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。
思路
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <algorithm> using namespace std; const int MAX_LEN = 210, MAX_K = 45, MAX_WORD_CNT = 10, MINF = 0xcfcfcfcf; int W[MAX_LEN][MAX_LEN], F[MAX_LEN][MAX_K]; string S, P[MAX_WORD_CNT]; int PCnt, K; void Read() { int lineCnt; cin >> lineCnt >> K; string temp; for (int i = 0; i < lineCnt; i++) { cin >> temp; S += temp; } cin >> PCnt; for (int i = 0; i < PCnt; i++) cin >> P[i]; } void GetW() { for (int j = 0; j < S.length(); j++) for (int i = j; i >= 0; i--) { int prevVal = i == j ? 0 : W[i + 1][j]; W[i][j] = prevVal; for (int p = 0; p < PCnt; p++) if (j - i + 1 >= P[p].length() && S.substr(i, P[p].length()) == P[p]) W[i][j] = prevVal + 1; } } int GetAns() { memset(F, MINF, sizeof(F)); for (int i = 0; i < S.length(); i++) F[i][1] = W[0][i]; for (int i = 0; i < S.length(); i++) for (int k = 2; k <= K; k++) for (int l = 0; l < i; l++) F[i][k] = max(F[i][k], F[l][k - 1] + W[l + 1][i]); return F[S.length() - 1][K]; } int main() { Read(); GetW(); printf("%d ", GetAns()); return 0; }