• 统计单词个数(codevs 1040)


    题目描述 Description

    给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)(管理员注:这里的不能再用指的是位置,不是字母本身。比如thisis可以算做包含2个is)。
    单词在给出的一个不超过6个单词的字典中。
    要求输出最大的个数。

    输入描述 Input Description

    第一行为一个正整数(0<n<=5)表示有n组测试数据
    每组的第一行有二个正整数(p,k)
    p表示字串的行数;
    k表示分为k个部分。
    接下来的p行,每行均有20个字符。
    再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)
    接下来的s行,每行均有一个单词。

    输出描述 Output Description

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

     

    样例输入 Sample Input

    1
    1 3
    thisisabookyouareaoh
    4
    is
    a
    ok
    sab

    样例输出 Sample Output

    7

    数据范围及提示 Data Size & Hint

    this/isabookyoua/reaoh

     
    /*
      划分性DP,用五重循环写的,数据太弱了,三重循环的没写出来
      f[i][j][k]表示把i-j分成k份的最大值。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<map>
    #define M 210
    #define N 35
    using namespace std;
    int f[M][M][N],n,p,m;
    string s,ci[7];
    map<string,bool> mp;
    void work()
    {
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++)
        {
            string c;cin>>c;
            s+=c;
        }
        n*=20;
        scanf("%d",&m);
        for(int i=1;i<=m;)
        {
            string c;cin>>c;
            if(!mp[c])
              ci[i]=c,i++,mp[c]=1;
            else m--;
        }
        for(int i=0;i<n;i++)
        {
            string ss="";
            for(int j=i;j<n;j++)
            {
                ss+=s[j];
                for(int k=1;k<=m;k++)
                {
                    int pos=0;
                    while(ss.find(ci[k],pos)<M)
                    {
                        pos=ss.find(ci[k],pos)+1;
                        f[i][j][1]++;
                    }
                }
            }
        }
        for(int len=1;len<=n;len++)
          for(int i=0;i+len-1<n;i++)
          {
              int j=i+len-1;
              for(int p1=1;p1<=min(len,p);p1++)
              for(int k=i+1;k<j;k++)
                for(int p2=1;p2<min(p1,k-i+1);p2++)
                {
                    if(p1-p2<=j-k)
                      f[i][j][p1]=max(f[i][j][p1],f[i][k][p2]+f[k+1][j][p1-p2]);
                }
          }
        printf("%d
    ",f[0][n-1][p]);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            memset(f,0,sizeof(f));
            s="";
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    在vm中安装ubuntu 11 并部署 xampp集成环境步骤
    修改xampp的mysql默认密码
    linux下重命名文件的命令
    IE6下DIV最小高度不能为0的解决方法
    linux下解压tar.gz 文件和 tar.bz2 文件命令
    linux svn 使用
    win7 下设置java环境变量
    在linux下安装svn软件rabbitvcs
    linux下开启ssh服务
    【转】DataSet与DataTable的区别
  • 原文地址:https://www.cnblogs.com/harden/p/5879709.html
Copyright © 2020-2023  润新知