提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
解题思路参考(感谢!!!)
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、怎么寻找两个字符串中最大相同子序列
当我们看到这个问题的时候,最多可能想的就是暴力解法,不停比较两个字符串中的相同部分,但是无疑,暴力解法在很多oj上是很难通过的!!!
所有我们就需要去寻找一些算法,以达到可以优化解题代码,使得其简单高效。
二、通过例题解析
1.动态规划解法
假设寻找字符串“abcbced”与字符串“acbcbcef”的最大相同子序列
算法思路:
1、把两个字符串分别以行和列组成一个二维矩阵。
2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。
3、通过查找出值为1的最长对角线就能找到最长公共子串。
针对于上面的两个字符串我们可以得到的二维矩阵如下:
此时运用dp就可以计算最大公共子串
可以通过一个二维数组来存结果->
if (s1[i] == s2[j])
{
a[i][j] = a[i-1][j-1] + 1;
}
代码:
#include <iostream>
#include <string>
#include <algorithm>
#define ll long long
using namespace std;
int main()
{
ll t;
cin >> t;
while (t--)
{
string s1;
string s2;
cin >> s1;
cin >> s2;
int maxx = -9999;//存取最大长度
int a[100][100];//存取结果
memset(a, 0, sizeof(a));//初始化为0
for (int i = 0; i < s1.size(); i++)
{
for (int j = 0; j < s2.size(); j++)
{
if (s1[i] == s2[j])
{
a[i+1][j+1] = a[i][j] + 1;//不断更新相同字符
maxx = max(maxx, a[i + 1][j + 1]);//更新最大相同子序列
}
}
}
cout << maxx << endl;
}
return 0;
}
2.STL优解
因为在解决该问题时,其实是不停对字符串进行处理,所有在STL中对string容器有许多的使用技巧:
我们在解决该问题的时候会用到主要两方面:
a:字符串的拼接
b:字符串的查找和替换
2->string容器的拼接
string s;
a:s+=(const char str)//重载+=操作符,实现将char类型字符串str拼接到字符串s后。
b:s+=(const string &str)//重载+=操作符,实现将字符串类型str拼接到字符串s后。
c:s+=(const char c)//重载+=操作符,实现将字符c拼接到字符串s后
d:s.append(const char *s1)//将char *类型字符串s1拼接到字符串s后
e:s.append(const string &s1)//将字符串类型s1拼接到字符串s后
f:s.append(const chars,int n)//将char *类型字符串拼接到字符串s后
g:s.append(const string &s1,int pos,int n)//将字符串s1从pos开始的n个字符串拼接到字符串s后
3->string容器的查找和替换
string s;
a:int k=s.find(const string &s1,int pos=0)//查找字符串s1在字符串s中从pops开始第一次出现的位置,若找到返回该位置,反之返回“-1”;
b:int k=s.find(const char *s1,int pos=0)//查找char 类型字符串s1第一次出现的位置,从pos开始查找,若存在返回该位置,反之返回“-1”;
c:int k=s.find(const chars1,int pos,int n)//从pos位置开始查找char类型字符串s1的前n个字符,第一次出现的位置,若存在返回该位置,反之返回“-1”。
d:int k=s.find(const char c,int pos=0)//从pos位置开始查找字符串s中字符c第一次出现的位置,若存在则返回该位置,反之返回“-1”;
e:int k=s.rfind(const string &str,int pos=s.size())//同上a,从后往前找,寻找最后一次出现的位置
f:int k=s.rfind(const char *s1,int pos=s.size())//同上b,从后往前找,寻找最后一次出现的位置
g:int k=s.rfind(const chars,int pos=s.size(),int n)//同上c,从后往前找,寻找最后一次出现的位置
h:int k=s.rfind(const char c,int pos=s.size(),int n)//同上d,从后往前找,寻找最后一次出现的位置
i:s.replace(int pos,int n,const string &str)//将字符串s从pos位置开始后n个字符,替换为字符串str。
j:s.replace(int pos,int n,const char std)//将字符串s从pos位置开始后n个字符,替换为char型字符串str。
STL解法的思路就像暴力解法一样,但是在进行“搜索操作”时,可以使用STL进行优化。
算法思路:
1:寻找字符串s1中的所有子串。
2:在字符串s2中寻找所有s1的子串,如果存在就记录该子串为相同子序列。
3:通过max不断更新最大相同子序列。
#include <iostream>
#include <string>
#include <algorithm>
#define ll long long
using namespace std;
int main()
{
ll t;
cin >> t;
while (t--)
{
string s1;
string s2;
cin >> s1;
cin >> s2;
int maxx = -9999;
for (int i = 0; i < s1.size(); i++)
{
for (int j = 1; j <= s1.size()-i; j++)
{
string str;
str.append(s1, i, j);//s1的子串
s2.find(str, 0);
int xx = str.size();
if (s2.find(str, 0) != -1) //相同子序列
{
maxx = max(xx, maxx);//更新最大相同子序列
}
}
}
cout<<maxx<<endl;
}
return 0;
}
3.实例(cf ->div3 #710 c)
题目链接
1->题目
outputstandard output
You are given the strings a and b, consisting of lowercase Latin letters. You can do any number of the following operations in any order:
if |a|>0 (the length of the string a is greater than zero), delete the first character of the string a, that is, replace a with a2a3…an;
if |a|>0, delete the last character of the string a, that is, replace a with a1a2…an−1;
if |b|>0 (the length of the string b is greater than zero), delete the first character of the string b, that is, replace b with b2b3…bn;
if |b|>0, delete the last character of the string b, that is, replace b with b1b2…bn−1.
Note that after each of the operations, the string a or b may become empty.
For example, if a=“hello” and b=“icpc”, then you can apply the following sequence of operations:
delete the first character of the string a ⇒ a=“ello” and b=“icpc”;
delete the first character of the string b ⇒ a=“ello” and b=“cpc”;
delete the first character of the string b ⇒ a=“ello” and b=“pc”;
delete the last character of the string a ⇒ a=“ell” and b=“pc”;
delete the last character of the string b ⇒ a=“ell” and b=“p”.
For the given strings a and b, find the minimum number of operations for which you can make the strings a and b equal. Note that empty strings are also equal.
Input
The first line contains a single integer t (1≤t≤100). Then t test cases follow.
The first line of each test case contains the string a (1≤|a|≤20), consisting of lowercase Latin letters.
The second line of each test case contains the string b (1≤|b|≤20), consisting of lowercase Latin letters.
Output
For each test case, output the minimum number of operations that can make the strings a and b equal.
2->分析:a:求出最大相同子序列
b:最大操作数=字符串s1的长度+字符串s2的长度-2*最大相同子序列长度
代码:
#include <iostream>
#include <string>
#include <algorithm>
#define ll long long
using namespace std;
int main()
{
ll t;
cin >> t;
while (t--)
{
string s1;
string s2;
cin >> s1;
cin >> s2;
int maxx = -9999;
for (int i = 0; i < s1.size(); i++)
{
for (int j = 1; j <= s1.size()-i; j++)
{
string str;
str.append(s1, i, j);
s2.find(str, 0);
int xx = str.size();
if (s2.find(str, 0) != -1)
{
maxx = max(xx, maxx);
}
}
}
if (maxx == -9999)
{
cout << s1.size() + s2.size() << endl;
}
else
{
int sum = s1.size() + s2.size() - 2 * maxx;
cout << sum << endl;
}
}
return 0;
}
如有错误,恳请指正!