题目地址:http://codevs.cn/problem/1040/
分析:
状态转移方程:f[i,j]=max(f[l,j-1]+total[l+1,i]) j<l<i
f[i,j]表示前i个字母分成j份所含的单词数,total[l+1,i]表示从l+1到i位所含的单词数
边界条件:f[i,1]=total[1,i]
f[n*20,k]即为答案
total数组也要用动态规划求,否则会超时
状态转移方程:total[i,j]=total[i,j-1]+word1(i,j) i>j
word1(i,j)是一个函数,用来求以第j位为结尾的单词数
边界条件:total[i,j]=word2(j) i=j
word2(j)是一个函数,用来求第j位是否是单词
代码:
var hash:array[0..200] of boolean;
total:array[0..200,0..200] of longint;
f:array[0..200,0..6] of longint;
nn,n,i,j,k,l,s,x,p:longint;
dic:array[1..6] of string;
st,t:string;
function max(a,b:longint):longint;
begin
if a>b then exit(a)
else exit(b);
end;
function word1(be,en:longint):longint;
var i:longint;
begin
word1:=0;
for i:=1 to s do
if (en-length(dic[i])+1>=be)and hash[en-length(dic[i])+1] and(copy(st,en-length(dic[i])+1,length(dic[i]))=dic[i]) then
begin
inc(word1);
hash[en-length(dic[i])+1]:=false;
end;
end;
function word2(j:longint):longint;
var i:longint;
begin
for i:=1 to s do
if (st[j]=dic[i]) and hash[j] then
begin
hash[j]:=false;
exit(1);
end;
word2:=0;
end;
begin
readln(nn);
for x:=1 to nn do
begin
fillchar(f,sizeof(f),0);
readln(p,k);
st:='';
for i:=1 to p do
begin
readln(t);
st:=st+t;
end;
n:=p*20;
readln(s);
for i:=1 to s do
readln(dic[i]);
for i:=1 to n do //求total数组
begin
fillchar(hash,sizeof(hash),true); //用来判重
for j:=i to n do
if i<>j then
total[i,j]:=total[i,j-1]+word1(i,j)
else
total[i,j]:=word2(j);
end;
for i:=1 to n do //赋初值
f[i,1]:=total[1,i];
for i:=2 to n do
for j:=2 to k do
if j<i then
for l:=j to i-1 do
f[i,j]:=max(f[l,j-1]+total[l+1,i],f[i,j]); //打擂台
writeln(f[n,k]);
end;
end.