【codechef】Magical Transformation(dp,技巧题)

91 篇文章 1 订阅
47 篇文章 0 订阅

Irfan and his brother Yusuf were looking at photographs of their vacation to Hawaii. Irfan noticed something interesting. He noticed that if their aunt Mansi had a big beard and a moustache she would resemble their uncle Amit. He tried to modify the people in other photographs in such a way so that they would resemble someone else. Yusuf who was into programming decided to do something similar with strings. He wrote down 2 words and tried to transform one word into another.

He decided that the operations that maybe performed on the strings could be: Inserting a character at any position, removing an existing character, modifying an existing character and swapping 2 adjacent characters. Each operation is counted as one move. While doing this he noticed that there is more than one way to complete this transformation. He wants your help to write a program that can find out the minimum number of moves required transform a given word into another given word.

Input

  • The first line contains a single integer T , the number of test cases. T test cases follow.
  • The only line of each test case contains 2 strings (contains only lower case letters), separated by a single space.

Output

For each test case, output a single line containing an integer which denotes the minimum number of moves required transform a given word into another given word.

Constraints

  • 1 ≤ T ≤ 1000
  • 1 ≤ |S| ≤ 100

 

Example

Input:
1
smatr smart

Output:
1

http://www.codechef.com/problems/MOUSCH01

有四种操作: Inserting a character at any position, removing an existing character, modifying an existing character and swapping 2 adjacent characters

问把一个字符串转变成另一个字符串所需要的最少操作数。

dp[i][j]表示取到A的前i位B的前j位时所需要的最少操作数。下面解释一下核心代码:

dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1首先考虑的是前三种操作。dp[i-1][j-1]是修改j位置上的值,dp[i-1][j]侧重在i<j的情况下删除j的末尾,dp[i][j-1]侧重在i>j的情况下在j的末尾插入值。接下来的代码考虑的是swap。由于是相邻,last数组记录字母在字符串中最后一次出现的位置,观察是否有其中一方要交换的两个字母刚好在相邻位置。如12345和15234,当前的两个末尾是4和5,分别在另一个字符串里查找4和5最后一次出现的位置,5->2,5->4,由于在A中4和5出现的位置相邻,那么我们可以选择交换4和5(+1),再加上dp[3][1]的状态,在此基础上往5后面插入2和3即可。

#include<iostream>  
#include<algorithm>  
#include<string>  
#include<map>  
#include<vector>  
#include<cmath>  
#include<string.h>  
#include<stdlib.h>  
#include<cstdio>  
#define ll long long  
using namespace std;  
int dp[101][101];
int last1[28],last2[28];
int main(){
	int t;
	cin>>t;
	while(t--){
		char x[105],y[105];
		cin>>x>>y;
		int len1=strlen(x),len2=strlen(y);
		for(int i=len1;i>=1;--i)
			x[i]=x[i-1];
		for(int i=len2;i>=1;--i)
			y[i]=y[i-1];
		for(int i=0;i<=len1;++i)
			dp[i][0]=i;
		for(int i=1;i<=len2;++i)
			dp[0][i]=i;
		memset(last1,-1,sizeof(last1));
		for(int i=1;i<=len1;++i){
			memset(last2,-1,sizeof(last2));
			for(int j=1;j<=len2;++j){
				if(x[i]==y[j])
					dp[i][j]=dp[i-1][j-1];
				else{
					dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1;
					if(last1[y[j]-'a']>0&&last2[x[i]-'a']>0){
						if(last1[y[j]-'a']==i-1)  //可以这样做的原因是[swapping 2 adjacent characters]
							dp[i][j]=min(dp[i][j],dp[last1[y[j]-'a']-1][last2[x[i]-'a']-1]+j-last2[x[i]-'a']-1+1);
						else if(last2[x[i]-'a']==j-1)
							dp[i][j]=min(dp[i][j],dp[last1[y[j]-'a']-1][last2[x[i]-'a']-1]+i-last1[y[j]-'a']-1+1);
					}
				}
				last2[y[j]-'a']=j;
			}
			last1[x[i]-'a']=i;
		}
		cout<<dp[len1][len2]<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值