来源:labuladong的算法小抄
题目:
现在有两个字符串s1和s2,请计算由s2转换成s1最少需要多少步?可以对字符串进行三种操作:插入一个字符,删除一个字符,替换一个字符。
例: s1 ="intention"
s2 = "execution"
结果:5
方法:
解决两个字符串的动态规划问题,一般都是用两个指针i,j分别指向两个字符串的最后,然后一步一步的往前走,缩小问题规模。
思想:
base case:i走完s1或者j走完s2 直接返回另一个字符串剩下的长度
对于每个字符s1[i]和s2[j],可以有以下四种操作:
if s1[i]== s2[j]{
啥都不做(skip)
i和j同时往前移动
}
else{
插入/删除/替换(三选一)
}
#include <iostream>
#include <cstring>
using namespace std;
//DP数组的方式进行优化
int min(int a, int b,int c)
{
int min=0;
if(a<b)
{
if(a<c)
min=a;
else
min=c;
}
else
{
if(b<c)
{
min=b;
}
else
{
min=c;
}
}
//cout<<"此时最小的是:"<<min<<endl;
return min;
}
int minDistance(char s1[],char s2[])
{
//利用strlen函数取得s1和s2数组的大小
int m = strlen(s1);
int n = strlen(s2);
int dp[m+1][n+1];
for(int i=0; i<=m; i++)
{
dp[i][0] = i;
}
for(int j=0 ; j<=m; j++)
{
dp[0][j]=j;
}
//进行状态转换,判断不进行处理还是进行处理,进行什么处理。自底向上的形式
for(int i =1; i<=m; i++)
{
for(int j =1; j<=n; j++)
{
//charAt()函数:可以返回指定位置的字符
//if(s1.charAt(i-1) == s2. charAt(j-1))
if(s1[i-1] == s2[j-1])
{
dp[i][j] = dp[i-1][j-1];
//cout<<"dp[][]============="<<dp[i][j]<<endl;
}
else
{
dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1);
}
}
}
cout<<"dp数组..................................."<<endl;
int count =0;
for(int i=0;i<=m;i++)
{
for(int j=0;j<=n;j++)
{
cout<<dp[i][j];
count ++;
if(count%(n+1) == 0)
{
cout<<endl;
}
}
}
cout<<"..................................."<<endl;
return dp[m][n];
}
int main()
{
char a[]="intention";
char b[]="execution";
int res = 0;
res = minDistance(a,b);
cout<<"res="<<res<<endl;
return 0;
}