• HW2016_字符串_STL_DP


    一、在字符串str1中删除那些在str2中出现的字符。

    str2可能会有重复字符,直接遍历会导致效率低下,故先借助STL的set容器对str1查重;

    然后,遍历str1和str2,对str1进行查重。

    #include <iostream>
    #include <string>
    #include <set>
    
    using namespace std;
    
    void deleteChar(char* strRet, const string& str1,int len1, const string& str2,int len2)
    {
        if(len1 < 1)                   //异常检测
        {
            return;
        }
        bool findIt = false;      //查找标记位
    
        set<char>mySet;
        int i = 0,j = 0,k = 0;
        for(i = 0; i < len2; ++i)  //str2去重复字符
        {
             mySet.insert(str2[i]);
        }
    
       for(j = 0; j < len1; j++)
        {
           for(set<char>::iterator it = mySet.begin(); it != mySet.end(); ++it)
           {
               if(str1[j] == *it && findIt == false)
               {
                   findIt = true;
                   break;
               }
           }//end for
    
           if(!findIt)
           {
               strRet[k++] = str1[j];
           }
           findIt = false;    //标记位置位
    
        }//end for
       strRet[k] = ''; //c风格字符串结束标志
    
    }
    
    int main()
    {
        string str1,str2;
        while(cin >> str1 >> str2)
        {
            int len1 = str1.size();
            int len2 = str2.size();
    char* strRet = new char[len1 + 1]; //申请空间存放查重后的字符串 deleteChar(strRet,str1,len1,str2,len2); cout << strRet << endl; delete strRet; //防止内存泄漏 return 0; } }

    二、

    编程题-成绩排名

    题目总共包含如下两种格式的字符串命令:

    1 LOD GRADE命令,其格式为:

    LOD GRADE:NAME=XiaoMing,MATH=80,LANG=90;

    (1)此命令用于导入学生成绩

    (2)NAME字段表示学生姓名

    (3)MATH字段表示学生数学成绩

    (4)LANG字段表示学生语文成绩

    (5)MATH字段和LANG字段顺序不一定是MATH在前,LANG在后

    (6)相同的分数,名词相同,后面的名次孔雀:例如100,99,99,99,98,98,名次1,2,2,2,5,5

    (7)此命令会连续执行,直到遇到第一个LST GRADE

    2 LST GRADE命令,其格式为:

    LST GRADE:NAME=XiaoHong;

    (1)此命令用于查询学生成绩

    (2)NAME字段表示学生姓名

    (3)查询结果格式:姓名 数学 语文 总分 数学排名 语文排名 总排名

    (4)每组用例,此命令仅执行一次

    样例输入

    LOD GRADE:NAME=XiaoMing,MATH=80,LANG=90;

    LOD GRADE:NAME=XiaoHong,LANG=60,MATH=100;

    LOD GRADE:NAME=XiaoMei,MATH=70,LANG=90;

    LST GRADE:NAME=XiaoHong;

    样例输出 XiaoHong 100 60 160 1 3 2

    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <cstdlib>
    
    using namespace std; 
    const string LOD = "LOD GRADE";
    const string LST = "LST GRADE";
    int myCout = 0;
    
    class student{
    public:
        student(string str)
        {
            OPE = "";
            unsigned int posOPE = str.find_first_of(':');
            if( posOPE < str.size())
                OPE = str.substr(0, posOPE);
            unsigned int posNAME1 = str.find_first_of('=');
            unsigned int posNAME2 = str.find_first_of(',');
            NAME = str.substr(posNAME1 + 1, posNAME2 - posNAME1 - 1);
    
            unsigned int posEnd = str.find_last_of(';');
            unsigned int posMATH = str.find_last_of('H');
            unsigned int posLANG = str.find_last_of('G');
            unsigned int posLastCommer = str.find_last_of(',');
    
            if(posEnd - posMATH > 5)
            {
                MATH = atoi(str.substr(posMATH + 2, posLastCommer - posMATH - 2).c_str());
                LANG = atoi(str.substr(posLastCommer + 6, posEnd - posLastCommer -6).c_str());
            }
            else
            {
                MATH = atoi(str.substr(posMATH + 2, posEnd - posMATH - 2).c_str());
                LANG = atoi(str.substr(posLANG + 2, posLastCommer - posLANG - 2).c_str());
            }
    
            totalScore = MATH + LANG;
            mathMarking = 0;
            langMarking = 0;
            totalMarking = 0;
            count = 0;
        }
        ~student(){}
        string OPE;
        string NAME;
        int MATH;
        int LANG;
        int totalScore;
        int mathMarking;
        int langMarking;
        int totalMarking;
        int count;
    };
    bool mathCompare(student*& stu1, student*& stu2)
    {
        return (stu1->MATH > stu2->MATH) ||
               (stu1->MATH == stu2->MATH && stu1->count < stu2->count);         //desc  ; 成绩相等,按照出现的顺序排序
    }
    bool langCompare(student*& stu1, student*& stu2)
    {
        return (stu1->LANG > stu2->LANG) ||
               (stu1->LANG == stu2->LANG && stu1->count < stu2->count);         //desc  
    }
    
    bool totalCompare(student*& stu1, student*& stu2)
    {
        return (stu1->totalScore > stu2->totalScore) ||
               (stu1->totalScore == stu2->totalScore && stu1->count < stu2->count);         //desc  
    }
    
    int main()
    {
        string str;
        vector<student* >students;
        while(getline(cin, str))   //去读一行,使用cin>>会有缓冲区的问题(空格,tab,回车)
        {
            //fill into vector
            student* stu = new student(str);
    
            if(LOD == stu->OPE)
            {
                students.push_back(stu);
                stu->count = myCout++;  //用于记录学生出现的顺序
            }
            if(LST == stu->OPE)
            {
               string stuName = "";     //提取学生姓名,用于匹配查找
               unsigned int posNAME01 = str.find_last_of('=');
               unsigned int posNAME02 = str.find_last_of(';');
               stuName = str.substr(posNAME01 + 1, posNAME02 - posNAME01 - 1);
    
                sort(students.begin(),students.end(),mathCompare);
                for(int i = 0; i < students.size();++i)
                {
                    if(students[i]->NAME == stuName)
                        students[i]->mathMarking = i+1;    //根据数学成绩排序规则,给学生的数学排名赋值
                }
                sort(students.begin(),students.end(),langCompare);
                for(int i = 0; i < students.size();++i)
                {
                    if(students[i]->NAME == stuName)
                        students[i]->langMarking = i+1;
                }
                sort(students.begin(),students.end(),totalCompare);
                for(int i = 0; i < students.size();++i)
                {
                    if(students[i]->NAME == stuName)
                        students[i]->totalMarking = i+1;
                }
                for(int i = 0; i < students.size();++i)
                {
                    if(students[i]->NAME == stuName)    //输出查找学生的信息
                    cout << students[i]->NAME << " " << students[i]->MATH << " "
                         << students[i]->LANG << " " << students[i]->totalScore << " "
                         << students[i]->mathMarking << " " << students[i]->langMarking
                         << " " <<students[i]->totalMarking;
                }
    
            }
    
        }//while
    
        return 0;
    }

    三、

    给出两个字符串A,B。将A字符串转化为B字符串,转化共两种方式:删除连续的n个字符,一次操作费用为2。增加连续的n个字符(增加的什么由你决定),一次操作的费用为n+2。求把A变为B最小费用。

    输入:第一行输入一个正整数(1<=T<=10),表示有T组测试数据。
    对于每组测试数据:
    两行字符串A,B(字符串长度不超过2000,字符仅包含小写字母。)

    输出:对于每组测试数据,输出一行一个整数,表示最小费用。
    样例输入
    2
    dsafsadfadf
    fdfd
    aaaaaaaa
    bbbbbbbb

    样例输出:
    7
    12

     分析:参考知乎(时间复杂度O(N3)),后面自己有时间复杂度O(N2)的方法。

    结尾应该只有三种情况即(不修改,删除结尾,添加结尾).
    1. 不修改, 只有当str1[j - 1] == str2[i - 1]的情况才可能存在, 此时费用等于将A[0:i-1]变换为B[0:j-1]的最小费用(三种方式中最小的那个),否则为INF
    2. 添加结尾, 考虑添加的长度为k,此时费用为将A[0:i]变换成B[0:j-k]再加上一个根据结尾不同变换的COST1
    3. 删除结尾, 考虑删除的长度为k,此时费用为将A[0:i-k]变换为B[0:j]再加上一个根据结尾不同变换的COST2
    (Delete: Min(F(0, m),...,F(n-1, m))+2;)
    ( Insert: Min(F(n,0)+m,...,F(n, m-1)+1)+2;)
    作者:AbmiP
    链接:https://www.zhihu.com/question/50960106/answer/123577803
    来源:知乎
    著作权归作者所有,转载请联系作者获得授权。
    
    #define _CRT_SECURE_NO_WARNINGS
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define INF 3000
    using namespace std;
    int de[2010][2010], ae[2010][2010], ne[2010][2010];
    char s1[2010], s2[2010];
    int main() {
        //freopen("io/in.txt", "r", stdin);freopen("io/out.txt", "w", stdout);
        int n, l1, l2;
        char c;
        scanf("%d%c", &n, &c);
        while (n--) {
            char* tmp = s1;
            char c;
            while ((scanf("%c", &c) != EOF) && c != '
    ')*(tmp++) = c;
            *tmp = '';
            tmp = s2;
            while ((scanf("%c", &c) != EOF) && c != '
    ')*(tmp++) = c;
            *tmp = '';
            l1 = strlen(s1);
            l2 = strlen(s2);
            for (int i = 0; i <= l1; i++) {
                de[0][i] = 2; ae[0][i] = ne[0][i] = INF;
            }
            for (int i = 0; i <= l2; i++) {
                ae[i][0] = i + 2; de[i][0] = ne[i][0] = INF;
            }
            ne[0][0] = 0;
            for (int j = 1; j <= l2; j++)
                for (int i = 1; i <= l1; i++) {
                    ne[j][i] = s1[i - 1] == s2[j - 1] ? min(min(ne[j-1][i-1], ae[j-1][i-1]), de[j-1][i-1]) : INF;
                    ae[j][i] = de[j][i] = INF;
                    for (int k = 1; k <= j; k++)
                        ae[j][i] = min(ae[j][i], min(ae[j - k][i] + k, min(de[j - k][i] + k + 2, ne[j - k][i] + k + 2)));
                    for (int k = 1; k <= i; k++)
                        de[j][i] = min(de[j][i], min(de[j][i - k], min(ae[j][i - k] + 2, ne[j][i - k] + 2)));
                }
            printf("%d
    ", min(min(ne[l2][l1], ae[l2][l1]), de[l2][l1]));
        }
        return 0;
    }

    O(N2):

    addEnd[i][j]表示通过增加字符,使得str1[0 : j]变换为str2[0 : i];

    delEnd[i][j]表示通过删除字符,使得str1[0 : j]变换为str2[0 : i];

    noEnd[i][j]表示不做变换,使得str1[0 : j]变换为str2[0 : i]。

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    #define max 2001
    #define INF 10000
    
    int addEnd[max][max];
    int delEnd[max][max];
    int noEnd[max][max];
    
    int MIN(int x,int y)
    {
        if(x>y)
            return y;
        else
            return x;
    }
    void initArray(int addEnd[][max], int delEnd[][max], int noEnd[][max], int len1, int len2)
    {
        for(int i = 0; i <= len1; i++)
        {
            delEnd[0][i] = 2;
            addEnd[0][i] = noEnd[0][i] = INF;
        }
        for(int i = 0;i <= len2; i++)
        {
            addEnd[i][0] = i + 2;
            delEnd[i][0] = noEnd[i][0] = INF;
        }
        noEnd[0][0] = 0;
    }
    void refreshArray(int addEnd[][max],int delEnd[][max],int noEnd[][max],const char* str1,int len1,const char* str2,int len2)
    {
        for(int i = 1;i <= len2; i++)
        {
            for(int j = 1;j <= len1; j++)
            {
                noEnd[i][j]  = (str1[j-1]==str2[i-1]) ? MIN(addEnd[i-1][j-1],MIN(delEnd[i-1][j-1],noEnd[i-1][j-1])) : INF;
    
                delEnd[i][j] = addEnd[i][j] = INF;
    
                addEnd[i][j] = MIN(addEnd[i][j], MIN(addEnd[i-1][j]+1, MIN(delEnd[i-1][j]+1+2, noEnd[i-1][j]+1+2)));
    
                delEnd[i][j] = MIN(delEnd[i][j],MIN(addEnd[i][j-1]+2,MIN(delEnd[i][j-1],noEnd[i][j-1]+2)));
    
            }
        }
    }
    
    int main()
    {
        int num;
        while(cin >> num)
        {
            int ret[num];
            int retID = 0;
            int retSize = num;
            while(num > 0)
            {
                char str1[max];
                char str2[max];
    
                cin >> str1 >> str2;
                int len1 = strlen(str1);
                int len2 = strlen(str2);
    
                //数组边界预定义
                initArray(addEnd, delEnd, noEnd, len1, len2);
                //刷新数组
                refreshArray(addEnd, delEnd, noEnd, str1, len1, str2, len2);
                //保存结果
                ret[retID++] = MIN(addEnd[len2][len1],MIN(delEnd[len2][len1],noEnd[len2][len1]));  
    //此处,切不可使用++retID(先自增为1,并将自增后的值赋给下标);而retID++是自增,并将自增前的值赋给小标。  回忆一下STL中map删除中 it++的用法
                --num;
            }//end while
            
            //result display
            for(int i = 0; i < retSize; i++)
            {
                cout << ret[i] << endl;
            }
        }//end while
        return 0;
    }
  • 相关阅读:
    【Java多线程 32】
    python中用input输入时可以回车换行(转帖)
    Python中自定义的实例通过网络进行传送
    《Python网络编程基础》第二章 读书笔记。
    redis操作记录!!!
    流畅的python,Fluent Python 第十五章笔记
    Python并行编程 中文版<中文笔记> 电子版[抄书笔记,仅供自己参考]待更新
    C Primer Plu学习笔记【5-6章节】
    curl使用指南(转帖)
    Python asyncio 异步编程参考资料(全部为url地址)
  • 原文地址:https://www.cnblogs.com/Lunais/p/5929406.html
Copyright © 2020-2023  润新知