zoukankan      html  css  js  c++  java
  • 统计单词个数

    题目描述

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

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

    要求输出最大的个数。

    输入输出格式

    输入格式:

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

    p表示字串的行数;

    k表示分为k个部分。

    接下来的p行,每行均有20个字符。

    再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)

    接下来的s行,每行均有一个单词。

    输出格式:

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

    输入输出样例

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

    思路:

    1,把很多行的串合并为一个串

    2,扫描串中所有的首字母,如果构成单词,把单词的结尾加入数组d中,那么 i,d[i] 就代表了一个单词的头尾

    3,从第一个字符开始进行递归的划分,直到只剩一次划分机会,就把剩下的所有字符都用上

    4,统计各段的单词之和,更新最大值(也就是枚举了所有的划分情况)

    统计各段单词利用数组d来完成,即检查以某个字母开头的单词结尾是否在这个段中,计算过的段结果保存起来,记忆化搜索

    下面上代码:

    #include<algorithm>
    using namespace std;
    #include<cstring>
    #include<vector>
    #include<cstdio>
    int p,k,s,e;
    char a[256];
    int d[256]={0};
    int dp[256][256]={0};
    struct Word{
        char s[128];        //单词信息 
        int len;            //单词长度 
    };
    Word w[6];
    //判断以i开头到r之间的串是否和单词j匹配 
    bool match(int i,int r,int j){
        if(r-i+1<w[j].len) return 0;        //剩余长度小于单词长度 
        for(int x=0;x<w[j].len;x++){
            if(a[i+x]!=*(w[j].s+x)) return 0;
        }
        return 1;
    }
    //统计l,r之间的单词数目,构造d[256]数组 
    int calc(int l,int r){
        int sum=0;
        for(int i=l;i<=r;i++){
            for(int j=0;j<s;j++){
                //对于同一个首字母,尽可能选取较短的单词进行匹配 
                if(d[i]-i+1>w[j].len&&match(i,r,j)==1){
                    d[i]=i+w[j].len-1;    //d[i]保存以i开头的单词的末尾 
                    //sum++;
                }
            } 
        }
        return sum;
    }
    int fun(int l,int r){
        if(dp[l][r]) return dp[l][r];
        int sum=0;
        for(int i=l;i<=r;i++){
            if(d[i]<=r) sum++;
        }
        return dp[l][r]=sum;
    }
    int wi=0,MAX=0;
    //s为开始点,k为剩余段数 
    void dfs(int s,int k){
        //只剩一次,全部分完
        int temp;
        if(k==1){
            temp=fun(s,e);
            wi+=temp;
            MAX=max(MAX,wi);
            wi-=temp;
            return;
        }
        for(int i=s;i<=e-k+1;i++){
            temp=fun(s,i);
            wi+=temp;
            dfs(i+1,k-1);
            wi-=temp;
        }
    }
    int main(){
        memset(d,127,sizeof(d));    //d[256]初始化为很大的常数
        scanf("%d%d",&p,&k);
        for(int i=0;i<p;i++){
            scanf("%s",&a[i*20]);
        }
        scanf("%d",&s);
        for(int i=0;i<s;i++){
            scanf("%s",w[i].s);
            w[i].len=strlen(w[i].s);
        }
        e=strlen(a)-1;
        calc(0,e);
        dfs(0,k);
        printf("%d
    ",MAX);
        return 0;
    }
  • 相关阅读:
    5个经典的javascript面试问题
    去年的一些面试题
    各种奇妙的hack
    jQuery工作原理解析以及源代码示例
    JavaScript Window
    原生JavaScript技巧大收集(1~10)
    蜘蛛爬虫类程序抓取有防盗链的网站处理 php和wget命令简单破解防盗链网站的功能
    Git SSH Key 生成步骤
    linux下ssh使用rsa认证教程
    linux FTP服务器 VSFTP配置手册
  • 原文地址:https://www.cnblogs.com/D-AngeloRussell/p/7234451.html
Copyright © 2011-2022 走看看