【动态规划】【poj 3267】The Cow Lexicon
问题
给定你一个字符串,和n个单词构成的字典。让你求出在字符串中最小删去几个字母,使得剩下的字符串能够由字典中的若干个单词构成。输出最少删去的字母的个数。
分析
如果考虑第i位的字母,当然只有要和不要两种状态,这是本题的突破口,是划分状态的根本。f[i]表示到第i位最少需要删除的字母的数目。那么得到如下的方程:f[i]:=min{f[i-1]+1,make(i)}不要当前的字母自然不需要解释,直接由相邻的状态更新,无后效性。如果要保留第i位,就需要函数解决。因为第i位的保留就必须有单词能够保留住它,也就会影响和它相邻的状态。当然不能简单地推。
至于make函数,如果要保留s[i],必有单词的最后一位恰好为s[i],所以枚举单词,在枚举如果用这个单词需要从该位开始删去前面的几个字母,到达什么位置。
显然make(i)=min{f[j](到达的位置)+该过程删去的字母}
code
program liukee;
var
n,len,i,temp:longint;
s:ansistring;
word:array[1..650] of string;
f:array[0..400] of longint;
procedure init;
var
i:longint;
begin
readln(n,len);
readln(s);
minlen:=maxlongint;
for i:=1 to n do
begin
readln(word[i]);
if word[i]<minlen then minlen:=word[i];
end;
end;
function make(k:longint):longint;
var
i,j,p,x:longint;
begin
make:=maxlongint;
if k<minlen then exit(maxlongint);
for i:=1 to n do
if s[k]=word[i][length(word[i])] then
begin
j:=k;
p:=length(word[i]);
while j>0 do
begin
if s[j]=word[i][p] then
dec(p);
dec(j);
if p=0 then break;
end;
if p<>0 then continue;
x:=k-j-p+f[j];
if x<make then make:=x;
end;
end;
begin
init;
f[0]:=0;
for i:=1 to len do
begin
temp:=make(i);
if temp<f[i-1]+1 then
f[i]:=f[i-1]+1
else f[i]:=temp;
end;
writeln(f[n]);
end.
反思
f[i]=min(max){f[i-1],function(i)}这是一类问题,要先找到第i个状态的转移。但该方程不和一般动归一样是由邻近的的状态更新来的,第i个状态的转移需要由第i-k个状态递推,才能满足没有后效性。
浙公网安备 33010602011771号