如何通过删除最少字符数来获取子字符串?

Posted

技术标签:

【中文标题】如何通过删除最少字符数来获取子字符串?【英文标题】:How to get a substring by deleting minimum number of characters? 【发布时间】:2019-12-12 19:55:07 【问题描述】:

在这个问题中,我们将 2 个字符串作为输入,例如 s1 和 s2。

现在,首先我们需要检查 s2 是否是 s1 的子序列。如果没有,请打印编号。

但如果是,我们需要打印从 s1 中删除的最小字符数才能得到 s2。

例如-thistext文本

这里可以直接找到文本,不删除任何字符,所以答案是0。

例如-可爱的友谊脆

在这种情况下,答案是 9。

到目前为止我做了什么,

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

int checkIfSub(string s1, string s2, int m, int n)

    int j = 0;
    for(int i = 0; i < m && j < n; i++)
        if(s1[i] == s2[j])
            j++;
    if(j == n)
        return 0;
    else 
        return 1;

int check(string s1, string s2)

    int count = 0; string s3;
    if(checkIfSub(s1, s2, s1.length(), s2.length()) == 1 || s2.length() > s1.length())
    
        cout << "NO\n"; return 0;
    
    int j = 0;
    for(int i = 0; i < s1.length(); i++)
    
        if(s1[i] == s2[j])
        
            s3[j] = s1[j];
            j++; continue;
        
        count++;
    
    cout << "YES " << count << "\n";
    return 0;


int main() 

    string s1, s2;
    cin >> s1 >> s2;
    check(s1, s2);

    return 0;

我的代码在第二个例子中运行良好,但在第一个例子中失败了。

(这是我在网上阅读的一些采访中提出的问题。)

【问题讨论】:

撇开其他问题不谈,您创建了空字符串s3,似乎使用s3[j] = s1[j] 语句无效地写入它,除此之外从不使用它。你能解释一下那部分代码吗? 不相关,但您应该查看Why should I not #include <bits/stdc++.h>? 和Why is “using namespace std;” considered bad practice? 以避免潜在问题。 我想你只是混淆了返回码checkIfSub。当s2的所有字符都匹配时,它真的应该返回0(false)吗? @FrançoisAndrieux OP 正在搜索子序列,而不是子字符串,即问题是,是否可以从 s1 中删除字符,使其变为 s2。因此crispCutefRIendShiP 的子序列(强调我的^^)。 OP:不管实现有什么问题,你的算法都太简单了,无法检查你想要检查的内容。它所做的只是计算s1.lenght() - s2.length()。您要么想对这个问题进行更多研究,要么自己思考解决这个问题的不同方法。 【参考方案1】:

试试这样的:

#include <iostream>
#include <string>
using namespace std;

bool check(const string &s1, const string &s2, int &minToDelete)

    minToDelete = 0;
    bool anySubSeqFound = false;

    if (s2.empty())
        return false;

    string::size_type first = 0;
    while ((first = s1.find(s2[0], first)) != string::npos)
    
        int numDeleted = 0;
        bool isSubSeq = true;

        string::size_type next = first + 1;
        for(string::size_type j = 1; j < s2.size(); ++j)
        
            string::size_type found = s1.find(s2[j], next);
            if (found == string::npos)
            
                isSubSeq = false;
                break;
            
            numDeleted += (found - next);
            next = found + 1;
        

        if (isSubSeq)
        
            if (anySubSeqFound)
            
                if (numDeleted < minToDelete)
                    minToDelete = numDeleted;
            
            else
                       
                anySubSeqFound = true;
                minToDelete = numDeleted;
            
        

        ++first;
    

    return anySubSeqFound;


int main()

    int minToDelete;

    if (check("thistext", "text", minToDelete))
        cout << "yes, delete " << minToDelete << endl;
    else
        cout << "no" << endl;

    if (check("cutefriendship", "crisp", minToDelete))
        cout << "yes, delete " << minToDelete << endl;
    else
        cout << "no" << endl;

Live Demo

【讨论】:

以上是关于如何通过删除最少字符数来获取子字符串?的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode1143. 最长公共子序列/300. 最长递增子序列//1713. 得到子序列的最少操作次数(好题!!!!!)

算法题2486. 追加字符以获得子序列

如何在批处理文件中获取带有特殊字符的子字符串?

如何根据字符获取子字符串并从右侧开始读取字符串

通过删除重复的子字符串组合两个字符串

我们如何通过重新排列字符串中的字符来获得最大数量的回文子串?