蓝桥杯 算法训练 统计单词个数

问题描述
  给出一个长度不超过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 3
thisisabookyouareaoh
4
is
a
ok
sab
样例输出
7
数据规模和约定
  长度不超过200,1<k<=40,字典中的单词数不超过6。


一个中等难度的模拟题,由于题干要求第一个字母不可以再次利用,我们只需要遍历这个字符串,看哪一个位置可以作为单词的起点,再统计单词的个数即可。

有个稍微难点的地方在于要把这个字符串分成k份,使分开后的单词个数最多,其实理解了以后也不难处理。很显然,最优处理方式一定是在不含单词的位置划分,这样的话单词个数就是上面统计出来的个数。可是,不含单词的位置可能比k要少,此时的划分就会不可避免的破坏单词,很显然,最优情况就是破坏一个单词(将边缘一个字母划分出去就行)。

我们遍历字符串每个单词是否匹配时,顺便把单词截止的字符串位置记录下来,用maxi和maxj变量表示出最靠后的截至位置,只有字符串遍历位置大于这个截止位置且遍历位置不作为单词首字母时,该位置就是不被单词包含的位置,在此处划分对单词个数无影响。

这样难点就都解决了,代码如下:
#include<cstdio>
#include<algorithm>
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;
char ch[10][20];
char ci[6][20];
int cnt=0;
bool pipei(int i,int j,int u,int &ii,int &jj)
{
    int len=strlen(ci[u]);
    for(int k=1;k<len;k++)
    {
        if(j+k>19)
        {
            i++;
            j=-k;
        }
        if(ch[i][j+k]!=ci[u][k])
        return false;
    }
    ii=i;
    jj=j+len-1;
    return true;
}
int main()
{
    int p,k,s;
    scanf("%d%d",&p,&k);
    for(int i=0;i<p;i++)
    {   getchar();
        for(int j=0;j<20;j++)
        scanf("%c",&ch[i][j]);
    }
    scanf("%d",&s);
    getchar();
    int flag;
    for(int i=0;i<s;i++)
    {
        scanf("%s",ci[i]);
    }
    int maxi=0,maxj=0,ii,jj;
    for(int i=0;i<p;i++)
    for(int j=0;j<20;j++)
    {   flag=0;
        for(int u=0;u<s;u++)
        if(ch[i][j]==ci[u][0])
        {
            if(pipei(i,j,u,ii,jj))
            {
                if(maxi<ii||(maxi==ii&&maxj<jj))
                 {maxi=ii;
                 maxj=jj;}
             cnt++;
             flag=1;
             break;
            }
        }
        if(flag==0&&k>1&&(i>maxi||(i==maxi&&j>maxj)))
        k--;
    }
    printf("%d\n",cnt-k+1);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/langzitan123/article/details/80178513