zoukankan      html  css  js  c++  java
  • 洛谷P1026 统计单词个数【区间dp】

    题目https://www.luogu.org/problemnew/show/P1026

    题意:

    给定一个字符串,要求把他分成k段。给定s个单词,问划分成k段之后每段中包含的单词和最大是多少。

    一个位置作为单词的开头只能计算一次。

    思路:

    如果仅仅是统计某一个区间内的最大单词数,这比较简单。每次从后往前推一个字符,如果这个字符是一个单词的开头,那么$cnt[i][j] = cnt[i+1][j]+1$

    但是现在要分成$j$段,这是状态之一,另一个状态应该是已经考虑前$i$个字符。

    也就是用$dp[i][j]$表示前$i$个字符划分成$j$段的最大单词数。

    很显然$dp[i][j] = dp[d][j-1] + cnt[d +1][i]$,也就是说在$0~i$之间找到一个位置$d$,从这里断开,前面的组成$j-1$段,后面的作为一个新的段。

    需要考虑的是,一个只有$i$个字符的字符串,最多只能划分成$i$段。

    并且要注意当$j =1$时需要特殊处理。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<map>
     4 #include<set>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<cmath> 
     9 #include<stack>
    10 #include<queue>
    11 #include<iostream>
    12 
    13 #define inf 0x7fffffff
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<string, string> pr;
    17 
    18 int p, k, s;
    19 const int maxn = 205;
    20 string str;
    21 string word[10];
    22 int cnt[maxn][maxn];
    23 int dp[maxn][maxn];
    24 
    25 int main()
    26 {
    27     scanf("%d%d", &p, &k);
    28     for(int i = 0; i < p; i++){
    29         string tmp;
    30         cin>>tmp;
    31         str += tmp;
    32     }
    33     scanf("%d", &s);
    34     for(int i = 1; i <= s; i++){
    35         cin>>word[i];
    36     }
    37     
    38     int len = str.length();
    39     
    40     for(int i = len - 1; i >= 0; i--){
    41         for(int j = i; j >= 0; j--){
    42             for(int x = 1; x <= s; x++){
    43                 int l = word[x].length();
    44                 if(str.substr(j, min(i - j + 1, l)) == word[x]){
    45                     cnt[j][i] = cnt[j + 1][i] + 1;
    46                     break;
    47                 }
    48                 else cnt[j][i] = cnt[j + 1][i];
    49                 //cout<<str.substr(j, min(i - j + 1, l))<<" "<<cnt[j][i]<<endl; 
    50             }
    51             
    52         }
    53     }
    54     
    55     for(int i = 1; i <= k; i++){
    56         dp[i][i] = dp[i - 1][i - 1] + cnt[i][i];
    57     }
    58     for(int i = 0; i < len; i++){
    59         dp[i][1] = cnt[0][i];
    60         for(int j = 2; j <= min(k, i); j++){
    61             for(int d = j - 1; d < i; d++){
    62                 dp[i][j] = max(dp[i][j], dp[d][j - 1] + cnt[d + 1][i]);
    63             }
    64         }
    65     }
    66     
    67     printf("%d
    ", dp[len - 1][k]);
    68     
    69     return 0; 
    70 }
  • 相关阅读:
    rails学习笔记(6)
    流程图好工具推荐JUDE
    流程图好工具推荐JUDE
    rails学习笔记(5)
    [转载 js]JsDoc Toolkit:Javascript文档利器
    ruby学习笔记(7)
    end_form_tag 已经在rails2.x中去掉了
    [转载 js]JsDoc Toolkit:Javascript文档利器
    rails学习笔记(5)
    ios 防止按钮快速点击造成多次响应的避免方法。
  • 原文地址:https://www.cnblogs.com/wyboooo/p/10851238.html
Copyright © 2011-2022 走看看