|NOIOJ|动态规划|2988:计算字符串距离

http://noi.openjudge.cn/ch0206/2988/

折腾了我很久,终于会了。。

设a数组为第一个字符串,b数组为第二个字符串,数组从下标1开始

对于这个问题,我们设f[i][j]为ai到bj的字符串距离(ai为a[1~i], bi为b[1~j])

设a数组的长度为m,b数组的长度为n


初始:

f[i][0] = i; (1<=i<=m)即为a数组有i个元素,b数组有0个元素

当b数组为空时,a数组到b数组的距离绝对是i

例如下面一组数据:

abcde
(空)

那么距离是什么呢?很显然,删除a数组的各个元素即可,因此距离为i

f[0][i] = i; (1<=i<=n)即为a数组有0个元素,b数组有i个元素

当a数组为空时,a数组到b数组的距离也绝对是i

理由同上,只是进行插入操作


那么下面有四种决策方案:

当a[i] = b[j]时 

1、f[i][j] = f[i-1][j-1]; 因为不需要进行操作,直接继承前面的即可

例如:

b
deb

当前i=1, j=3, 因为a[i] = b[j]问题可以转化为

(空)
de
即转化为ai-1到bj-1的距离

否则

2、f[i][j] = min(f[i-1][j-1]+1); 把a[i]改为b[i], 使他们相等, 因为改了以后,a[i]=b[j],所以可以转化为上面的方法

例如:

c
deb
当前i=1, j=3, 改a[i]为b[j], 则有
b
deb
就变成上面的那个了,这里不再重复讲。

3、f[i][j] = min(f[i][j-1]+1); 在a[i]后面插入b[j]

例如:

c
deb

当前i=1, j=3, 在a[i]后面插入b[j], 则有

cb
deb
当前a[i+1]=b[j],则有

c
de
所以转化成了 ai到bj-1的距离
4、f[i][j] = min(f[i-1][j]+1); 删除a[i]
例如:

c
deb
当前i=1, j=3, 删除a[i], 则有
(空)
deb
即转化为ai-1到bj的距离

最后答案为f[n][m].

#include
#include  
#include   
#include 
#define ms(i,j) memset(i, j, sizeof(i)); 
using namespace std;
char a[1005], b[1005]; 
int f[1005][1005];
int main()  
{
	int t;
	scanf("%d\n", &t);
	while (t--)
	{
		scanf("%s%s", a+1,b+1);
		int m1 = strlen(a+1), m2 = strlen(b+1);
		f[0][0] = 0;
		for (int i=1;i<=m1;i++) f[i][0] = i;
		for (int i=1;i<=m2;i++) f[0][i] = i;
		for (int i=1;i<=m1;i++)
		for (int j=1;j<=m2;j++)
		{
			if (a[i]==b[j]) 
			{
				f[i][j] = f[i-1][j-1];
			}
			else
			{
				f[i][j] = min(f[i-1][j-1], min(f[i-1][j], f[i][j-1]))+1;
			}
		} 
		printf("%d\n", f[m1][m2]);
	}
    return 0;  
}  


你可能感兴趣的:(算法讨论,动态规划,Vijos)