单词在给出的一个不超过6个单词的字典中。
要求输出最大的个数。
p表示字串的行数;
k表示分为k个部分。
接下来的p行,每行均有20个字符。
再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)
接下来的s行,每行均有一个单词。
thisisabookyouareaoh
4
is
a
ok
sab
一个中等难度的模拟题,由于题干要求第一个字母不可以再次利用,我们只需要遍历这个字符串,看哪一个位置可以作为单词的起点,再统计单词的个数即可。
有个稍微难点的地方在于要把这个字符串分成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;
}