公共字串计算(最长公共子串/序列)C++

来源:互联网 发布:nginx 400 错误 编辑:程序博客网 时间:2024/05/17 05:57

题目

描述

题目标题:
计算两个字符串的最大公共字串的长度,字符不区分大小写

输入

输入两个字符串

输出

输出一个整数

样例输入

asdfas werasdfaswer

样例输出

6

思路

暴力求解
此题用cin即可

代码

#include <iostream>#include <string>using namespace std;int Maxsubstr(string a,string b){    unsigned int start1,start2;    int count=0,Max=0;    for(unsigned int i=0; a[i]!='\0'; i++)    {        for(unsigned int j=0; b[j]!='\0'; j++)        {            start1=i;            start2=j;            while(a[start1]==b[start2] && start1<a.length() && start2<b.length())            {                start1++;                start2++;                count++;            }            if(count>Max)            {                Max=count;            }            count=0;        }    }    return Max;}int main(){    string str1,str2;    cin>>str1;    cin>>str2;    //不区分大小写    for (unsigned int i=0; i<str1.length(); i++)    {        str1[i]=tolower(str1[i]);    }    for (unsigned int i=0; i<str2.length(); i++)    {        str2[i]=tolower(str2[i]);    }    cout<<Maxsubstr(str1,str2)<<endl;}

这里写图片描述

题目

描述

查找两个字符串a,b中的最长公共子串。
详细描述:
查找两个字符串a,b中的最长公共子串。

输入

输入两个字符串

输出

返回重复出现的字符

样例输入

abcdefghijklmnop
abcsafjklmnopqrstuvw

样例输出

jklmnop

思路

暴力求解

代码

#include <iostream>#include <string>using namespace std;int Maxsubstr(string a,string b,string *&s){    unsigned int start,start1,start2;    int count=0,Max=0;    for(unsigned int i=0; a[i]!='\0'; i++)    {        for(unsigned int j=0; b[j]!='\0'; j++)        {            start1=i;            start2=j;            while(a[start1]==b[start2] && start1<a.length() && start2<b.length())            {                start1++;                start2++;                count++;            }            if(count>Max)            {                start = i;                Max = count;            }            count=0;        }    }    //保存字符串    s=new string[Max+1];    for(int i=0; i<Max; i++)    {        s[i]=a[i+start];    }    s[Max]='\0';    return Max;}int main(){    string str1,str2,*str;        cin>>str1>>str2;    //此题输入-------------    //getline(cin,str1);    //getline(cin,str2);    int length = Maxsubstr(str1,str2,str);    for(int i=0; i<length; i++)    {        cout<<str[i];    }    cout<<endl;    return 0;}
这里写图片描述 这里写图片描述

如果你看到这里觉得暴力方法low

Low。。。。

哎,那就聊聊动态规划版的经典问题《最长公共子串(序列)》

子串是连续的,子序列可以是不连续的。

状态转移方程:

符号约定,C1是S1的最右侧字符,C2是S2的最右侧字符,S1‘是从S1中去除C1的部分,S2’是从S2中去除C2的部分。

LCS(S1,S2)等于下列3项的最大者:

(1)LCS(S1,S2

(2)LCS(S1,S2)

(3)LCS(S1,S2’)–如果C1不等于C2; LCS(S1,S2)+C1 —如果C1等于C2;

边界终止条件:如果S1和S2都是空串,则结果也是空串。

下面我们同样要构建一个矩阵来存储动态规划过程中子问题的解。这个矩阵中的每个数字代表了该行和该列之前的LCS的长度。与上面刚刚分析出的状态转移议程相对应,矩阵中每个格子里的数字应该这么填,它等于以下3项的最大值:

(1)上面一个格子里的数字

(2)左边一个格子里的数字

(3)左上角那个格子里的数字(如果 C1不等于C2); 左上角那个格子里的数字+1( 如果C1等于C2)

#include<iostream>#include<cstring>#include <vector>using namespace std;void SubSequence(vector<vector<string>> &flag,string str1, string str2,int i,int j);void display(int *result,string str1,string str2);void initialVector(vector<vector<string>> &vectorAll,int len){    for(int i=0; i<len; ++i)    {        vector<string> temp;        vectorAll.push_back(temp);    }}int lcs_string(string str1, string str2){    int len1 = str1.length();    int len2 = str2.length();    int result = 0;     //记录最长公共子串长度    int c[len1+1][len2+1] ;    int endPos = -1;    for (int i = 0; i <= len1; i++)    {        for( int j = 0; j <= len2; j++)        {            if(i == 0 || j == 0)            {                c[i][j] = 0;            }            else if (str1.at(i-1) == str2.at(j-1))            {                c[i][j] = c[i-1][j-1] + 1;                result = max(c[i][j], result);                if(result==c[i][j])  endPos = i;//记录最后一个点的位置            }            else            {                c[i][j] = 0;//重新计数            }        }    }    //print result    string str="";    if(endPos<=len1)    {        str = str1.substr(endPos-result,result);    }    else    {        str = str2.substr(endPos-result,result);    }    cout<<"\n\nLongest Common Substring : "<<str<<endl;    return result;}//对于最长公共子序列,只是在最后一个else里面放的是前两步的最大值int lcs_squence(string str1, string str2){    int len1 = str1.length();    int len2 = str2.length();    int c[len1+1][len2+1];    vector<vector<string>> flag;    initialVector(flag,len1+1);    for (int i = 0; i <= len1; i++)    {        for( int j = 0; j <= len2; j++)        {            if(i == 0 || j == 0)            {                c[i][j] = 0;                flag[i].push_back("NULL");            }            else if (str1.at(i-1) == str2.at(j-1))            {                c[i][j] = c[i-1][j-1] + 1;                flag[i].push_back("left_up");            }            else if(c[i - 1][j]>=c[i][j - 1])            {                c[i][j]=c[i - 1][j];                flag[i].push_back("left");            }            else            {                c[i][j] = c[i][j - 1];                flag[i].push_back("up") ;            }        }    }    //display(&c[0][0],str1,str2);  //输出数组    SubSequence(flag,str1,str2,str1.length(),str2.length());    //cout<<c[len1][len2]<<endl;    return c[len1][len2];}void display(int *result,string str1,string str2){    int len1 = str1.length();    int len2 = str2.length();    //输出表头    for(int i=0; i<=len2; ++i)    {        cout<<"\t"<<str2[i];    }    cout<<endl;    //输出数组    for(int i=0; i<=len1; ++i)    {        cout<<str1[i]<<"\t";        for(int j=0; j<=len2; ++j)        {            cout<<*result<<"\t";            result++;        }        cout<<endl;    }}//按照方向查找void SubSequence(vector<vector<string>> &flag,string str1, string str2,int i,int j){    if (i == 0 || j == 0)        return;    if (flag.at(i).at(j) == "left_up")    {        cout<<str2[j - 1]<<" ("<< i - 1<<" , "<< j - 1<<")"<<endl;        //左前方        SubSequence(flag,str1,str2,i - 1, j - 1);    }    else    {        if (flag.at(i).at(j) == "up")        {            SubSequence(flag,str1,str2,i, j - 1);        }        else        {            SubSequence(flag,str1,str2,i - 1, j);        }    }}int main(){    string X = "";    string Y = "";    //输入    getline(cin,X);    getline(cin,Y);    cout<<"\nFirst string:\n"<<X<<endl;    cout<<"\nSecond string:\n"<<Y<<endl;    cout << "Length of Longest Common Substring is " << lcs_string(X, Y)<<endl;    cout << "Length of Longest Common Subsequence is " << lcs_squence(X, Y)<<endl;    return 0;}

这里写图片描述

参考引用

传送门 : 最长公共子序列

传送门 : 最长公共子序列(LCS)C++实现

传送门 : 最长公共子序列与最长公共子串

传送门 : 最长公共子序列。。

传送门 : 最长公共子序列。。大杂烩

0 0