划分型动态规划 之 CODE[VS] 1040 统计单词个数 2001年NOIP全国联赛提高组

/*
dp[i][k] := 前i+1个字符组成的字符串,划分为k份,每份中包含的单词个数加起来总数的最大值。
 
初始化:
	dp[][] = -0x3f3f3f3f  
// 注意:对于dp[i][k],若(i+1)<k,则dp[i][k]的值不存在,设为-0x3f3f3f3f。例如:dp[0][2] = -0x3f3f3f3f  dp[i][1] = val[0][i]   //注:val[i][j] := 截取原字符串【从i到j的字符(包含i和j位置的字符)】组成字符串,返回其包含的单词个数 状态方程: dp[i][k] = max(dp[i][k], dp[j][k-1]) + Num(j+1, i)) (0<=j<i) 答案: dp[len-1][k] 此题难点:求val[i][j] val[i][j] = val[i][j-1] + num(j) num(j) := 遍历所有想要匹配的字符串strArr[m],从原字符串strS位置j出发向前找字符,找到一个首字符位置fst, 使得strS[fst,j]的长度刚好等于strArr[m],若满足以下条件: 1)i<=fst<=j        对应代码:(j - i + 1) >= strArr[m].size() 2)此字符串首字符的位置fst在求val[i][j-1]和求num(j)时,没有用过 对应代码:!used[j - strArr[m].size() + 1] 3)strS[i,j] == strArr[m] 对应代码:strSource.substr(j - strArr[m].size() + 1, strArr[m].size()) == strArr[m] 则:+1 最后找到几个满足这三个条件的首位置fst,num(j)的值就是几。 */
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstddef>
  5 #include <iterator>
  6 #include <algorithm>
  7 #include <string>
  8 #include <locale>
  9 #include <cmath>
 10 #include <vector>
 11 #include <cstring>
 12 using namespace std;
 13 const int INF = -0x3f3f3f3f;
 14 const int MaxN = 210;
 15 const int MaxK = 50;
 16 
 17 int dp[MaxN][MaxK];
 18 int val[MaxN][MaxN];
 19 int len, K, S;
 20 string strSource;
 21 string strArr[10];
 22 
 23 
 24 void iniVal()
 25 {
 26     bool used[MaxN];
 27     for (int i = 0; i < len; ++i)
 28     {
 29         memset(used, 0, sizeof(used));
 30         for (int j = i; j < len; ++j)
 31         {
 32             if (i != j) val[i][j] = val[i][j - 1];
 33             for (int m = 0; m < S; ++m)
 34             {
 35                 if ((j - i + 1 >= strArr[m].size()) && !used[j - strArr[m].size() + 1]
 36                     && (strSource.substr(j - strArr[m].size() + 1, strArr[m].size()) == strArr[m]))
 37                 {
 38                     ++val[i][j];
 39                     used[j - strArr[m].size() + 1] = true;
 40                 }
 41             }
 42         }
 43     }
 44 }
 45 
 46 void Solve()
 47 {
 48     for (int i = 0; i < len; ++i)
 49     {
 50         dp[i][1] = val[0][i];
 51     }
 52     for (int i = 0; i < len; ++i)
 53     {
 54         for (int j = 0; j < i; ++j)
 55         {
 56             for (int k = 2; k <= K; ++k)
 57             {
 58                 dp[i][k] = max(dp[i][k], dp[j][k - 1] + val[j+1][i]);
 59                 int bbb = 1;
 60             }
 61         }
 62     }
 63     cout << dp[len-1][K] << endl;
 64 
 65 
 66 
 67     /*cout << "



" << "val:----------------------------" << endl;
 68     for (int i = 0; i < len; ++i)
 69     {
 70         for (int j = 0; j < len; ++j)
 71         {
 72             cout << val[i][j] << " ";
 73         }
 74         cout << endl;
 75     }
 76 
 77     cout << "



" << "dp:----------------------------" << endl;
 78     for (int i = 0; i < len; ++i)
 79     {
 80         for (int j = 1; j <= K; ++j)
 81         {
 82             cout << dp[i][j] << " ";
 83         }
 84         cout << endl;
 85     }*/
 86 }
 87 
 88 int main() 
 89 {
 90 #ifdef HOME
 91     freopen("in", "r", stdin);
 92     //freopen("out", "w", stdout);
 93 #endif
 94 
 95     int cas;
 96     cin >> cas;
 97     while (cas--)
 98     {
 99         strSource = "";
100         memset(val, 0, sizeof(val));
101         for (int i = 0; i < MaxN; ++i)
102         {
103             for (int j = 0; j < MaxK; ++j)
104             {
105                 dp[i][j] = INF;
106             }
107         }
108         int p;
109         cin >> p >> K;
110         string strTmp;
111         for (int i = 0; i < p; ++i)
112         {
113             cin >> strTmp;
114             strSource += strTmp;
115         }
116         len = strSource.size();
117         cin >> S;
118         for (int i = 0; i < S; ++i)
119         {
120             cin >> strArr[i];
121         }
122         iniVal();
123         Solve();
124     }
125 
126 #ifdef HOME
127     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
128     _CrtDumpMemoryLeaks();
129     system("pause");
130 #endif
131     return 0;
132 }


 
原文地址:https://www.cnblogs.com/shijianming/p/4996481.html