1. 程式人生 > >洛谷 P1026 統計單詞個數

洛谷 P1026 統計單詞個數

int copy 初始 不能 false void check 下標 設置

題目描述

給出一個長度不超過200的由小寫英文字母組成的字母串(約定;該字串以每行20個字母的方式輸入,且保證每行一定為20個)。要求將此字母串分成k份(1<k40),且每份中包含的單詞個數加起來總數最大(每份中包含的單詞可以部分重疊。當選用一個單詞之後,其第一個字母不能再用。例如字符串this中可包含thisis,選用this之後就不能包含th)。

單詞在給出的一個不超過6個單詞的字典中。

要求輸出最大的個數。

輸入輸出格式

輸入格式:

每組的第一行有2個正整數(p,k)

p表示字串的行數,k表示分為k個部分。

接下來的p行,每行均有20個字符。

再接下來有1個正整數s,表示字典中單詞個數。(1s6)

接下來的s行,每行均有1個單詞。

輸出格式:

1個整數,分別對應每組測試數據的相應結果。

輸入輸出樣例

輸入樣例#1:
1 3
thisisabookyouareaoh
4
is
a
ok
sab
輸出樣例#1:
7

說明

this/isabookyoua/reaoh

解題思路:

本題需先看另一篇博客:https://www.cnblogs.com/lipeiyi520/p/10414227.html

本題是一個DP題,用一個f數組表示狀態,其中f[i][j]表示到了第i個位置,分了j塊,能得到的最多的單詞數,再枚舉斷點l,則 dp[i][j]=max{ dp[i][j] , dp[l][j-1]+sum[l+1][i] };sum[i][j]表示i到j的單詞數.

AC代碼:

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 int p,k,n,m,sum[210][210],f[210][50];
 5 string s,a[10];
 6 bool check(int l,int r) {//判斷是否有單詞以s[l]為開頭
 7     string x = s.substr(l,r - l + 1);//取出字符串 
 8     for(int i = 1;i <= n; i++) if(!x.find(a[i])) return true
;//查找 9 return false; 10 } 11 void inin() {//讀入+預處理 12 string ch; 13 s += 0;//下標從0開始 14 scanf("%d%d",&p,&k);//輸入 15 for(int i = 1;i <= p; i++) { 16 cin >> ch; 17 s += ch; 18 } 19 scanf("%d",&n); m = s.length() - 1;//下標從0開始,所以要減一 20 for(int i = 1;i <= n; i++) cin >> a[i];//輸入單詞 21 for(int i = m;i >= 1; i--) 22 for(int j = i;j >= 1; j--) {//預處理sum[i][j] 23 sum[j][i] = sum[j+1][i]; 24 if(check(j,i)) sum[j][i]++; 25 } 26 } 27 void dp() {//開始DP 28 f[0][0] = 0; 29 for(int i = 1;i <= k; i++) f[i][i] = f[i-1][i-1] + sum[i][i]; 30 for(int i = 1;i <= m; i++) f[i][1] = sum[1][i];//初始化 31 for(int i = 1;i <= m; i++) 32 for(int j = 1;j <= k && j < i; j++) 33 for(int l = j;l < i; l++)//設置斷點 34 f[i][j] = max(f[i][j],f[l][j-1] + sum[l+1][i]); 35 printf("%d\n",f[m][k]); 36 } 37 int main() 38 { 39 inin(); 40 dp(); 41 return 0; 42 }

洛谷 P1026 統計單詞個數