1. 程式人生 > >【CJOJ1644】【洛谷2758】編輯距離

【CJOJ1644】【洛谷2758】編輯距離

題面

題目描述

設A和B是兩個字串。我們要用最少的字元操作次數,將字串A轉換為字串B。這裡所說的字元操作共有三種:
1、刪除一個字元;
2、插入一個字元;
3、將一個字元改為另一個字元;
皆為小寫字母

輸入格式:

第一行為字串A;第二行為字串B;字串A和B的長度均小於2000。

輸出格式:

只有一個正整數,為最少字元操作次數。

Input

sfdqxbw
gfdgw

Output

4

題解

一道DP裸體
先設一下狀態
設f[i][j]表示串S1前i個字元到串S2前j個字元的編輯距離

看一看每一個f[i][j]可以怎麼得到:
如果當前有S1[i]=S2[j]那麼f[i][j]=f[i-1][j-1],直接由前面的狀態就可以得到
否則:
1. 可以由i-1和j-1的匹配情況加上一次修改操作
2. 可以由i-1和j 的匹配情況加上一次刪除操作
3. 可以由i 和j-1的匹配情況加上一次新增操作

所以狀態轉移方程就可以得出來了

後面就不用寫了,直接看程式碼吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
string s1,s2;//初始字串 
int l1,l2;
int f[5000][5000];
int main()
{
      cin>>s1>>s2;
      l1=s1.length();
      l2=s2.length();
      memset
(f,127,sizeof(f)); //f[i][j]表示把 s1前i位變為 s2的前j位的 最短編輯距離 for(int i=0;i<=l2;++i) f[0][i]=i; for(int i=0;i<=l1;++i) f[i][0]=i; for(int i=1;i<=l1;++i) { for(int j=1;j<=l2;++j) { if(s1[i-1]==s2[j-1]) f[i][j]=min(f[i][j],f[i-1
][j-1]);//如果兩位相同 else f[i][j]=min(f[i][j],f[i-1][j-1]+1);//上一位的基礎上加"替換" f[i][j]=min(f[i][j],f[i][j-1]+1);//上一個的基礎上加"新增" f[i][j]=min(f[i][j],f[i-1][j]+1);//上一位的基礎上加"刪除" } } cout<<f[l1][l2]<<endl; return 0; }