您的位置:首页 > 其它

洛谷 P1026 统计单词个数

2017-02-10 12:06 141 查看
题目描述

给出一个长度不超过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

说明

this/isabookyoua/reaoh

注意:

两个单词开头不能相同,就是在this 包含this 和 is,但this 和 th 只能算其中一个。

分析:先预处理出每一个区间有多少个单词,然后再跑dp,设f[i,j]为切割i次,前j项最多有多少个单词,则

f[i,j]=max(f[i-1,k]+sum[k+1,j]) (1<k<j)

代码:

var
s:string;
p,k,n,l:longint;
a:array [1..6] of string;
sum:array [1..200,0..200] of longint;
f:array [1..40,0..200] of longint;

procedure init;
var i:longint;
t:string;
begin
readln(p,k);
for i:=1 to p do
begin
readln(t);
s:=s+t;
end;
readln(n);
for i:=1 to n do
readln(a[i]);
end;

function poss(h,t:longint):boolean;
var tt:string;
i:longint;
begin
tt:=copy(s,h,t-h+1);
for i:=1 to n do
if pos(a[i],tt)=1 then exit(true);
exit(false);
end;

procedure try;
var i,j:longint;
begin
l:=length(s);
for i:=l downto 1 do
for j:=i to l do
if poss(i,j) then sum[i,j]:=sum[i+1,j]+1
else sum[i,j]:=sum[i+1,j];
end;

function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
procedure dp;
var i,j,h:longint;
begin
f[1]:=sum[1];
for i:=2 to k do
for j:=i-1 to l do
for h:=i-1 to j-1 do
begin
f[i,j]:=max(f[i-1,h]+sum[h+1,j],f[i,j]);
end;
writeln(f[k,l]);
end;

begin
init;
try;
dp;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: