1.
有3个字母a,b,c:你输入一个数字,要输出所有的组合字符和组合数
输入1 , 输出a,b,c 3
输入2 , 输出aa,ab,ac,ba,bb,bc,ca,cb,cc 9
笛卡尔乘积的思想,只需写一个单次乘积的函数,循环n次即可
#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<string> dikaer(vector<string> v1, vector<string> v2)
{
vector<string> res;
for (int i = 0; i < v1.size(); i++)
for (int j = 0; j < v2.size(); j++)
res.push_back(v1[i] + v2[j]);
return res;
}
int main()
{
vector<string> v{ "a","b","c" },res;
res = v;
int n;
cin >> n;
while (--n) // n=1 时则无需执行
res = dikaer(res, v); //笛卡尔乘积
int i;
for (i = 0; i < res.size()-1; i++)
cout << res[i] << ',';
cout << res[i] << ' ' << res.size();
}
2.
求字符串1与字符串2的最大公共子串的长度及此最大公共子串的个数。
输入 abcdefg (最大公共子串:bcd)
Eebcdfg
输出 3 1
输入 abcdefg (最大公共子串为:abcd defg)
abcddefg
输出 4 2
2.1动态规划解法
复杂度为o(mn)。
相比于上一篇博客中求最大公共子串的那道题,本题在求长度的基础上增加了求公共子串的个数。
思路是不再以dp[n][m]
作为最大公共子串的保存位置。而使用maxi
保存当前最大长度。每当要刷新maxi
这个值时,将存储最大串个数的num
置为1。此后,若执行dp[i][j] = dp[i - 1][j - 1] + 1;
后的dp[i][j]
再度为maxi,说明又出现长度为maxi的串,num++。
运行后的dp数组:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string a, b;
int maxi, num;
while (cin >> a, cin >> b) {
maxi = 0;
int dp[101][101] = { 0 };
for (int i = 0; i <= a.length(); i++) {
for (int j = 0; j <= b.length(); j++) {
if (i == 0 || j == 0) { //有一个为空串时,最长公共串长度为0
dp[i][j] = 0;
continue;
}
if (a[i - 1] == b[j - 1]) { //减一是因为dp的边必须填充为0
dp[i][j] = dp[i - 1][j - 1] + 1;
if (dp[i][j] > maxi) {
num = 1;
maxi = dp[i][j];
}
else if (dp[i][j] == maxi)
num++;
}
}
}
cout << maxi << ' ' << num << endl;
}
}
2.2 四层暴力解法
o(m2n2)的复杂度
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a,b;
cin >> a >> b;
int max = 0;
int num;
for(int i=0;i<a.length();i++){
for(int ii=i+1;ii<=a.length();ii++){
for(int j=0;j<b.length();j++){
for(int jj=j+1;jj<=b.length();jj++){
string tmp1 = a.substr(i,ii-i);
string tmp2 = b.substr(j,jj-j);
if(tmp1 == tmp2){
if(ii-i == max){ //这个if要在上
num++;
}
if(ii-i > max){
max = ii-i;
num = 1;
}
}
}
}
}
}
cout << max << ' ' << num << endl;
}