统计单词个数(划分型)
codevs 1040 統計單詞個數
2001年NOIP全國聯賽提高組
?題目等級 : 黃金 Gold 題目描述?Description給出一個長度不超過200的由小寫英文字母組成的字母串(約定;該字串以每行20個字母的方式輸入,且保證每行一定為20個)。要求將此字母串分成k份(1<k<=40),且每份中包含的單詞個數加起來總數最大(每份中包含的單詞可以部分重疊。當選用一個單詞之后,其第一個字母不能再用。例如字符串this中可包含this和is,選用this之后就不能包含th)(管理員注:這里的不能再用指的是位置,不是字母本身。比如thisis可以算做包含2個is)。
單詞在給出的一個不超過6個單詞的字典中。
要求輸出最大的個數。
第一行為一個正整數(0<n<=5)表示有n組測試數據
每組的第一行有二個正整數(p,k)
p表示字串的行數;
k表示分為k個部分。
接下來的p行,每行均有20個字符。
再接下來有一個正整數s,表示字典中單詞個數。(1<=s<=6)
接下來的s行,每行均有一個單詞。
每行一個整數,分別對應每組測試數據的相應結果。
樣例輸入?Sample Input1
1 3
thisisabookyouareaoh
4
is
a
ok
sab
7
目標:前i個字符中劃分為j個部分包含的單詞數
如果知道i——j包含的單詞數,動態規劃可推出答案。
若想知道i——j包含的單詞數,處理出以每個位置為起點是否有單詞、單詞長度可推出。
所以:
ans[j][i]表示前j個字符劃分為i個部分包含的單詞數
預處理:f[i][j] i——j包含的單詞數 ? g[i]=j 以i為起點有長為j的單詞
f數組處理:如果i+g[i]-1<=j,那么f[i][j]里包含以i為起點長為j的單詞
狀態轉移:ans[j][i]=max(ans[k][i-1]+f[k+1][j])
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int T,p,k,sum,g[401],f[201][201],ans[201][41]; string s,ss,word[7]; int len_tot,len[7]; void pre() {s.clear();for(int i=1;i<=6;i++)word[i].clear();memset(g,0,sizeof(g));memset(f,0,sizeof(f));memset(ans,0,sizeof(ans)); } int main() {scanf("%d",&T);while(T--){pre();scanf("%d%d",&p,&k);while(p--){cin>>ss;s+=ss;}len_tot=s.length();scanf("%d",&sum);for(int i=1;i<=sum;i++) cin>>word[i];for(int i=1;i<=sum;i++) len[i]=word[i].length();memset(g,127,sizeof(g));for(int i=0;i<len_tot;i++)for(int j=1;j<=sum;j++)if(s.substr(i,len[j])==word[j]&&g[i]>len[j]) g[i]=len[j];for(int i=0;i<len_tot;i++)for(int j=i;j<len_tot;j++)for(int l=i;l<=j;l++){if(g[l]>400) continue;if(l+g[l]-1<=j) f[i][j]++;} for(int i=0;i<len_tot;i++) ans[i][1]=f[0][i];for(int i=2;i<=k;i++)for(int j=i;j<len_tot;j++)for(int l=i-1;l<j;l++)ans[j][i]=max(ans[j][i],ans[l][i-1]+f[l+1][j]);printf("%d\n",ans[len_tot-1][k]);} }?
?
轉載于:https://www.cnblogs.com/TheRoadToTheGold/p/6358958.html
總結
以上是生活随笔為你收集整理的统计单词个数(划分型)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消息队列NetMQ 原理分析2-IO线程
- 下一篇: 梦到吃粉条和肉是什么意思