1. 最长回文串
输入一个字符串,输出其最长回文串的长度,以及最长回文串的个数,不区分大小写。例如
输入:aB 输出: 1 2
输入:aBA 输出: 3 1
输入:aaaa 输出: 4 1
写了一个字符串逆序的方法,遍历所有子串
#include<iostream>
#include<string>
#include<vector>
using namespace std;
string reverse(string t)
{
char c;
string :: iterator b = t.begin(), e = t.end()-1;
while(b < e){
c = *b; *b = *e; *e = c;
b++;
e--;
}
return t;
}
int main()
{
string s, tmp;
string::iterator it1, it2;
int max_leng, num;
while(cin >> s)
{
for(int i = 0; i < s.length(); i++)
s[i] = tolower(s[i]);
max_leng = num = 0;
for(it1 = s.begin(); it1 != s.end(); it1++){
for(it2 = it1;it2!=s.end();it2++){
tmp = string(it1,it2+1); //构造一个子串
if(tmp == reverse(tmp)){
if(tmp.length() > max_leng){
max_leng = tmp.length();
num = 1;
}
else if(tmp.length() == max_leng)
num++;
}
}
}
cout << max_leng << ' ' << num << endl;
}
}
2.
任何一个大于2的偶数均可表示为两个素数之和。输入m, n(6<=m<=n<=50),则把[m, n]内的所有偶数表示成两个素数之和的形式。输出这些素数及其出现的次数,输出次序按照素数出现的次数从多到少输出;若出现次数相同,按照素数从大到小输出;若偶数有多种素数相加形式,则把所有的情况都输出,每种情况占一行。
- 输入:8 9
- 输出:
5 1 3 1 - 输入:9 10
- 输出:
5 2
7 1 3 1 - 输入:14 15
- 输出:
7 2
11 1 3 1 - 输入:8 10
- 输出:
5 3 3 1
3 2 7 1 5 1
本题难度主要在于在不同偶数之间、不同分解的组合上。
从最简单的数据结构上来看,至少需要一个三维数组:v[50][50][50]
第一维代表[m,n]范围内的第几个偶数,第二维代表该偶数的第几种分解方式,第三维代表该分解方式下的一个质数,值代表的是该质数出现的次数。
例如:对于m=8,n=10
- v[0][0][5] = 1、v[0][0][3] = 1
- v[1][0][5] = 2、v[1][1][7] = 1、v[1][1][3] = 1
- 其余值均为0
看起来很浪费空间,而且这么写会使后面的排序输出非常麻烦,于是将最后一维替换为map<int,int>类型。不过map<int,int>仅仅是为了保证插入的唯一性和便捷性而采用的中间结构,由于map不允许排序,故需要在排序前先转化为vector<int,int> pair<int,int>类型。
数据结构为vector<vector<map<int,int> > > v;
再让第二维的不同元素之间的不同分解方法做笛卡尔积,保存在vector<map<int, int> > res
之中。
最后排序并输出即可
#include<iostream>
#include<vector>
#include<map>
#include<math.h>
#include<algorithm>
using namespace std;
vector<vector<map<int, int> > > v;
vector<map<int, int> > res; //笛卡尔积的result
typedef vector<map<int, int> > D;
void insert(map<int, int> m1, map<int, int>& res)
{
for (auto it = m1.begin(); it != m1.end(); it++) {
int l = it->second;
while (l > 0) { //l为几就加几次 <===> res[it->first] += it->second
res[it->first]++;
l--;
}
}
}
bool cmp(pair<int, int> p1, pair<int, int> p2)
{
if (p1.second != p2.second)
return p1.second > p2.second;
return p1.first > p2.first;
}
D dikaer(D d1, D d2)
{
if (d1.size() == 0) //第一次不用乘,直接返回d2
return d2;
vector<map<int, int> > res;
for (int i = 0; i < d1.size(); i++) {
for (int j = 0; j < d2.size(); j++) {
map<int, int> tmp;
insert(d1[i], tmp); //tmp是个引用,将d1[i]的所有pair插入tmp中
insert(d2[j], tmp);
res.push_back(tmp);
}
}
return res;
}
bool zhishu(int n) //n为质数则返回true
{
if (n <= 1)
return false;
for (int i = 2; i <= sqrt(n); i++) {
if (n % i == 0)
return false;
}
return true;
}
int main()
{
int m, n;
while (cin >> m, cin >> n) {
v.clear();
res.clear();
map<int, int> tmp;
int a = 0;
for (int i = m; i <= n; i++) {
int b = 0;
if (i % 2 != 0)
continue; //用i遍历m~n的所有偶数
for (int j = 2; j < i / 2 + 1; j++) { //用j遍历i的所有质数
vector<map<int, int> > tv;
v.push_back(tv); //装个空容器防止越界
if (zhishu(j) && zhishu(i - j)) {
map<int, int> tm;
v[a].push_back(tm); //同理
v[a][b][j]++;
v[a][b][i - j]++;
b++; //分解方式++
}
}
a++; //偶数数量++
}
for (int i = 0; i < a; i++) //做笛卡尔乘积
res = dikaer(res, v[i]);
for (auto it = res.begin(); it != res.end(); it++) { //排序并输出
vector<pair<int, int> > r(it->begin(), it->end()); //注意是pair,不能用vector :(
sort(r.begin(), r.end(), cmp);
for (auto ite = r.begin(); ite != r.end(); ite++) {
cout << ite->first << ' ' << ite->second << " ";
}
cout << endl;
}
}
}
这道题我在VS强大的debug下还写了好久才写对,要是在考场上怕是凉凉了