查找两个字符串中相同字符串_使两个字符串相同的最低成本

查找两个字符串中相同字符串

Problem statement:

问题陈述:

Given two strings string1 and string2 find the minimum cost required to make the given two strings identical. We can delete characters from both the strings. The cost of deleting a character from string1 is costX and string2 is costY. The cost of removing any characters from the same string is the same. Like, removing any

给定两个字符串, string1string2找到使给定两个字符串相同所需的最低成本。 我们可以从两个字符串中删除字符。 从string1删除字符的成本为costX,string2costY 。 从同一字符串中删除任何字符的成本是相同的。 喜欢,删除任何

    Input:
    The first line contains integers costX and costY.
    The second line contains the two strings X and Y.

    Output:
    Print the total cost to make the two strings 
    equal for each test case in a new line.

    Constraints:
    1<= length of strings X and Y <=1000
    1<= costX, costY <=1000

Explanation of Example:

示例说明:

    Input:
    1
    10 20
    "acba" "acdb"

    Output:
    30

    Explanation:
    The similar strings would be "acb". 
    So need to remove one from string1 and one from string2 
    costing total of 30.

Solution Approach:

解决方法:

The problem can be solved recursively,

该问题可以递归解决,

Let,

让,

    N = length of string1
    M = length of string1
    F(n,m) = minimum cost to make two strings similar

Let us consider, what can be cases that can arrive for F(i,j) where 0 <= i<n && 0 <= j<m

让我们考虑一下,对于F(i,j) ,其中0 <= i <n && 0 <= j <m

Case 1.

情况1。

string1[i]==string2[j] that is indexed characters are similar

索引字符的string1 [i] == string2 [j]相似

In such a case, we don't need any additional cost to make strings similar, the cost will be similar to sub-problem of size i-1, j-1. This can be recursively written as

在这种情况下,我们不需要使字符串相似的任何额外费用,该费用将类似于大小为i-1 , j-1的子问题。 这可以递归写成

    F(i,j) = F(i-1,j-1) if string1[i] == string2[j]

Case 2.

情况2

string1[i]!=string2[j] that is indexed characters are not similar.

索引字符的string1 [i]!= string2 [j]不相似。

In such a case we need to invest,

在这种情况下,我们需要投资,

  1. One thing can remove the indexed character from string1 and change to indexed string2 character.

    一件事可以从字符串 1中删除索引的字符,然后更改为索引的string2字符。

    This can be recursively written as,

    可以将其写为

        F(i,j) = F(i-1,j) + costX if string1[i] != string2[j]
    
    
  2. Another way can be to remove the indexed character from string2 and change to string1 indexed character.

    另一种方法是从string2删除索引字符,然后更改为string1索引字符。

    This can be recursively written as,

    可以将其写为

        F(i,j) = F(i,j-1) + costY if string1[i] != string2[j]
    
    
  3. Remove characters from both.

    从两者中删除字符。

    This can be recursively written as,

    可以将其写为

        F(i,j) = F(i-1,j-1) + costY + costX if string1[i] != string2[j]
    
    Finally, we would take minimum out of this three cases.
    

So here goes the problem structure,

所以这里是问题的结构,

Now the above recursion will create many overlapping subproblems and hence we need two converts it into DP.

现在,上述递归将创建许多重叠的子问题,因此我们需要两次将其转换为DP。

Converting into DP

转换为DP

    n = string1 length
    m = string2 length
    str1 = string1
    str2 = string2

    1)  Declare int dp[n+1][m+1];
    2)  Base case
            for i=0 to n
                dp[i][0]=i*costX;
            for j=0 to m
                dp[0][j]=j*costY;
    3)  Fill the DP
            for i=1 to n
                for j=1 to m
                    //first case when str1[i-1]==str2[j-1]
                    dp[i][j]=dp[i-1][j-1];  
                    if(str1[i-1]!=str2[j-1])
                        dp[i][j]+=costX+costY;
                        dp[i][j]=min(dp[i][j],min(dp[i-1][j]+costX,dp[i][j-1]+costY));
                    end if
            
                end for
            end for
    4)  return dp[n][m]; 

C++ Implementation:

C ++实现:

#include <bits/stdc++.h>
using namespace std;

int editdistance(string s1, string s2, int costX, int costY)
{

    int n = s1.length();
    int m = s2.length();
    int dp[n + 1][m + 1];
    
    for (int i = 0; i <= n; i++)
        dp[i][0] = i * costX;
    
    for (int j = 0; j <= m; j++)
        dp[0][j] = j * costY;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            dp[i][j] = dp[i - 1][j - 1];
            if (s1[i - 1] != s2[j - 1]) {
                dp[i][j] += costX + costY;
                dp[i][j] = min(dp[i][j], min(dp[i - 1][j] + costX, dp[i][j - 1] + costY));
            }
        }
    }
    
    return dp[n][m];
}

int main()
{
    int costX, costY;
    
    cout << "Cost of changing/removing character from string1: \n";
    cin >> costX;
    
    cout << "Cost of changing/removing character from string2: \n";
    cin >> costY;
    
    string s1, s2;
    
    cout << "Input string1\n";
    cin >> s1;
    cout << "Input string2\n";
    cin >> s2;
    
    cout << "Minimum cost to make two string similar: " << editdistance(s1, s2, costX, costY) << endl;

    return 0;
}

Output

输出量

Cost of changing/removing character from string1: 
2
Cost of changing/removing character from string2: 
3
Input string1
includehelp
Input string2
includuggu
Minimum cost to make two string similar: 22


翻译自: https://www.includehelp.com/icp/minimum-cost-to-make-two-strings-identical.aspx

查找两个字符串中相同字符串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面试题,是纸上写的,发现了些错误,回来改进了下。写纸上和写计算机里并编译成功完全是两个效果。 开始没太多字符串操作,很繁琐、难点也多,后逐渐改进。 典型问题1: sizeof()局限于栈数组 char a[] = "asd213123123"; 形式,并且这种不能用'\0'判断是否结束(这种判断方式能很方便加在while条件用于判断越界——b != '\0')。 如果是字符串常量: char *b = "dasadafasdf"; 这种情况,sizeof()就废掉了! 总之: 对号入座,前者sizeof、后者strlen~!不过sizeof(a)和strlen(b)还有另外一个区别,strlen不计算'\0',而sizeof要计算(前提是sizeof()不针对char指针) 典型问题2: 用什么来暂存并输出结果?还是只是记录下来相关位置——这是我底下未完成版本1想到的思路——用一个count[sizeof(A)]数组记录下A每个位置作为起点所能和B达到的最大重合,最后判断查找数组最大值,此时目标子字符串的起点下标(i)和 i 对应的长度(counter[i])都有了。 这是针对不知道字符串大小并且不占用额外空间的做法,需要非常繁琐的操作,要加很多标记,越界判断也会有些麻烦(结合优势么,用字符串常量而不是栈空间字符数组,有'\0'——就好判断了!) (关于空间的占用,如果要用一个和字符串a一样长的数组counter来计录a各起点对应与b最大重合子字符串,这个数组也要和a一样长,空间上也不合适,除非情形很特殊,a短b长,不然不如直接malloc()一个堆空间来储存当前最长“子字符串”,并实时更新) 先放一个改完编译测试成功的。 release1 //题目:要求比较A字符串(例如“abcdef"),B字符串(例如(bdcda)。找出重合度最大的子字符串,输出(根据OJ经验,输>出结果对即可) #include #include #include main(){ char *A = "abcderfghi"; char *B = "aderkkkkkabcd"; int i,j,c = 0,count = 0; unsigned int maxSeg = 0; int max = strlen(A) > strlen(B) ? strlen(A) : strlen(B); char* final = (char*)malloc(sizeof(char) * (max + 1)); final[max] = '\0'; for(i = 0;A[i] != '\0';i++){ for(j = 0;B[j] != '\0';j++){ while(A[i + c] == B[j] && A[i+c] != '\0' && B[j] != '\0'){ count++; c++; j++; }                         if(count > maxSeg){                                 strncpy(final,(A + i),count);                                 maxSeg = count;                         } count = 0; c = 0; } } printf("%s\n",final); free(final); } 这是能将就用的第一个版本~!关于结束符'\0'能否影响free()的使用,觉得是完全不用操心的,因为malloc的大小是系统来保存的,删除时候系统来接手就完了,而'\0'结束符只是针对一些常规字符串操作,比如printf()用%s控制输出时~! 新难点:找到的子字符串同时一样长怎么办?那我这只能叫做”第一个最长的重合字符串“用两块空间来存储?三
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值