题目一:USACO 2007 Open 最近回文
题目描述:
给出一个由前N (1 ≤ N ≤ 26)个小写字母组成的字串,长度为M (1 ≤ M ≤ 2,000) ,可以在任意位置插入或者删除字符,给出每种字母插入删除的代价。
求把字串修改成回文串的最小总代价。
样例输入:
3 4
abcb
a 1000 1100
b 350 700
c 200 800
样例输出:
900
思路:逼近法
增加该字母与删去该字母的效果是一样的,开一个cost数组取两者间的最小值表示修改该字母。
状态&状态转移方程:
f[i][j]表示将第i位到第j位的子串改为回文串的代价。
f[i+1][j-1]; (str[i]==str[j])
f[i][j]= min(f[i+1][j]+cost[i] , f[i][j-1]+cost[j]); (str[i]!=str[j])//因为删除的cost一定是正值所以当str[i]==str[j]的时候就不考虑删改i或j了。
删改左边的字符 删改右边的字符
题目二:UVa1626 括号序列
题目描述:
定义如下正则括号序列:
1.空序列是正则括号序列。
2.如果S是正则括号序列,那么(S)和[S]也是正则括号序列。
3.如果A和B都是正则括号序列,那么AB也是正则括号序列。
输入一个长度为n的,仅由(、)、[、]构成的序列,添加尽量少的括号,得到一个正则括号序列。输入串长度不超过100。
样例输入:
1
([(]
样例输入:
()[()]
思路:枚举断开点
状态&状态转移方程:
f[i][j]表示从第i个括号到第j个括号要配成正则括号序列最少额外需要的括号数。
f[i+1][j-1] (str[i]与str[j]可以配对)
f[i][j]=min(f[i][k]+f[k+1][j]) (注意这里没有str[i]与str[j]必须不能配对的限制,原因是str[i]与str[j]可能是两个不同的正则括号序列【条件3】,如"[][]")
输入解直接用s[i][j]保存f[i][j]的最优决策点k,dfs一遍即可。
注:该题之所以不能用逼近法(与题1的区别)就是因为存在多个正则括号序列,如果去掉法则3就和题1没什么区别了。
题目三:POJ1229 模糊匹配
题目描述:
给定两个模糊域名串s和t,每个串用圆点分成若干个部分(part),由英文字母和通配符组成。3种通配符的含义分别是:
*:匹配一个或多个部分;
?:匹配至少一个至多三个部分;
!:匹配至少三个部分。
通配符单独被分隔成一个部分。
问两个模糊域名串是否能够匹配。匹配是指至少能构造一个域名能匹配两个模糊串。
例如www.xyz.edu能匹配www.?.edu和?.edu
样例输入:
2
www.?.edu
?.edu
*.edu
yahoo.com
样例输出:
YES
NO
思路:LCS模型(两个字符串)
通配符的一陪有限个或有限个配任意的限制过于繁琐,变为一配一或者一配任意个就可以随意使用LCS模型了。
定义通配符如下:
@:匹配一个部分
#:匹配一个部分或啥都不匹配
$:匹配一个部分或多个部分
改造原有的通配符如下:
*:$
!:@@$
?:@##
如此一来,状态&状态转移方程:
f[i][j](bool)表示str1前i位与str2前j位是否能匹配。
边界条件:f[0][0]=1;
f[i][j]=f[i][j] || f[i-1][j-1] (str1[i]=='@')
f[i][j]=f[i][j] || f[i-1][j-1] || f[i-1][j] (str1[i]=='#') ->考虑str1的当前状态
f[i][j]=f[i][j] || f[i-1][j-1] || f[i][j-1] (str1[i]=='$')
f[i][j]=f[i][j] || f[i-1][j-1] (str2[i]=='@')
f[i][j]=f[i][j] || f[i-1][j-1] || f[i][j-1] (str2[i]=='#') ->考虑str2的当前状态(与str1相反)
f[i][j]=f[i][j] || f[i-1][j-1] || f[i-1][j] (str2[i]=='$')