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

      

    题目描述

    给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个)。要求将此字母串分成kk份(1<k le 401<k40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串thisthis中可包含thisthis和isis,选用thisthis之后就不能包含thth)。

    单词在给出的一个不超过66个单词的字典中。

    要求输出最大的个数。

    输入输出格式

    输入格式:

    每组的第一行有22个正整数(p,kp,k)

    pp表示字串的行数,kk表示分为kk个部分。

    接下来的pp行,每行均有2020个字符。

    再接下来有11个正整数ss,表示字典中单词个数。(1 le s le 61s6)

    接下来的ss行,每行均有11个单词。

    输出格式:

    11个整数,分别对应每组测试数据的相应结果。

    输入输出样例

    输入样例#1: 复制
    1 3
    thisisabookyouareaoh
    4
    is
    a
    ok
    sab
    
    输出样例#1: 复制
    7
    

    说明

    this/isabookyoua/reaoh

    一共有两个dp

    第一个dp为预处理

    必须要从后往前转移  这样遇到重复的也不会影响结果   如题意所得  每次判断具有后效性   所以当遇到这种情况的时候一定要从后往前dp  之前有一道安排工作的dp也是一样!!!!

    注意 预处理的细节

    第二个dp为区间dp

    划分为k个区域只要加上k-1个隔板即可

    然后就是注意 区间dp各种小细节!!!!

    我做的时候有个疑问  为什么分隔点是s后面  而不能是当前处理区间末尾的前面一格分隔  

    想一想就知道是错的!!!。。。

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define LL long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 2147483647
    #define N 200
    string s;
    int k,q,n;
    string table[10];
    int word[210][210];
    int dp[210][50];
    int len;
    bool check(int i,int j)
    {
       /* string temp=s.substr(i,j-i+1);
        rep(i,1,q)if(temp.find(table[i])==0)return true;
        */
        rep(k,1,q)
        {
            if(table[k].size()>j-i+1)continue;
            if(s.substr(i,table[k].size())==table[k])return true;
        }
        return false;
    }
    void init()
    {
        repp(j,len,1)
        repp(i,j,1)
        {
            word[i][j]=word[i+1][j];
            if(check(i,j))word[i][j]++;
        }
    }
    int main()
    {
        RII(n,k);
        rep(i,1,n)
        {
            string temp;
            cin>>temp;
            s+=temp;
        }
        len=s.size();
        s='*'+s;//方便处理
        RI(q);
        rep(i,1,q)
        cin>>table[i];
        init();
        rep(i,1,len)
        dp[i][0]=word[1][i];
    
        rep(i,1,k-1)//加入k-1个 分隔   最后就会分成k块
        rep(j,i+1,len)
        rep(s,i,j-1)//枚举断点s
        dp[j][i]=max(dp[j][i],dp[s][i-1]+word[s+1][j]);//我不知道为什么改成word[s][j-1]不行 (否则 第三层循环没有任何意义  答案永远不会再更新了!!!)
    
        cout<<dp[len][k-1];
    }
    View Code
  • 相关阅读:
    043 抖音短视频爬取实战
    048 Python里面yield的实现原理
    047 Python面试知识点小结
    001 Glang实现简单分布式缓存
    046 算法的时间复杂度和空间复杂度计算
    042 使用Python远程监视多个服务器和数据库的状态,python,监控,同步
    041基于python实现jenkins自动发布代码平台
    045 chrome浏览器前端调试技巧
    STL学习
    Asio与Boost.Asio
  • 原文地址:https://www.cnblogs.com/bxd123/p/10687311.html
Copyright © 2011-2022 走看看