1、碎片字符串
形如aabbaaacaa的字符串,可分为五个相同连续字母组成的碎片:‘aa’,‘bb’,‘aaa’,‘c’,‘aa’,其中每个碎片只出现一次,即该字符串包含’aa’,‘bb’,‘aaa’,'c’四个碎片,且输出时按字典序排序。
输入:aabbaaacaa
输出:
aa
aaa
bb
c
1.模拟过程,每次把得到子串的长度放到一个二维数组里,各行按a~z索引,每一列记录子串长
思想:先记录信息到一张表,再从表中取出数据
#include <iostream>
#include <cmath>
#include<string>
using namespace std;
#define check(c) cout<<c<<endl
int data_[28][20];
int getpos(int hang,int n){//第i行里有没有n
bool flag = false;
int i = 0;
for (; i < 20&&data_[hang][i]!=-1; i++) {
if (data_[hang][i] == n) {
flag = true;
break;
}
}
if (!flag) {
return i;
}
return -1;
}
void show(int i, int n) {
string str="";
char c = i-1 + 'a';
while (n--) {
str += c;
}
cout << str << endl;
}
int main() {
//data
for (size_t i = 0; i < 28; i++)
{
for (size_t j = 0; j < 20; j++) {
data_[i][j] = -1;
}
}
//input
string str = "";
cin >> str;
//count
int i = 0;
while (i < str.size()) {
char ch = str.at(i);
int num = 0;
//字符的下标一定要先检查后访问
while (i<str.size()&&str.at(i) == ch) {
i++;
num++;
}
if (num) {
int j = ch - 'a'+1;
int c = getpos(j,num);
if (c != -1)
data_[j][c] = num;
}
}
//output
for (int i = 1; i < 27; i++) {
if (data_[i][0] != -1) {
//check(i);
for (int j = 0; j < 20&&data_[i][j] != -1; j++){
//输出访问之前数据要合理
show(i, data_[i][j]);
}
//check(i);
}
}
//system("pause");
return 0;
}
1.2,借助数组set的元素唯一性,将所有的子串加入到一个set中,最后输出结果
#include<iostream>
#include<set>
#include<string>
using namespace std;
int main() {
//data
set<string> set_str;
string str = "";
//input
cin >> str;
//exe
for (int i = 0; i < str.length(); i++) {
string temp = "";
temp += str[i];
while (str[i] == str[i + 1]) {
temp += str[i++];
}
set_str.insert(temp);//这一步是核心,将重复子串删除
}
//output
for(string s: set_str) {
cout << s << endl;
}
return 0;
}
2、哈夫曼树
输入n,以及n个数(用,隔开),构造哈夫曼树,输出其最小带权路径长度
思想:不断合并最小的两个数,并且更新他的权重,使得新值的和合并前的值等价
输入:
4
2,4,5,7
输出:35
输入:
4
1,1,1,1
输出:8
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
#define check(x) cout<<x<<endl
typedef struct weight_ {
int num;
double weight;
}Wt;
Wt arr[30];
void get_arr(string str) {
int t = 0;
for (int i = 0; i < str.length(); ++i) {
if (str.at(i) != ',') {
arr[t].num = str.at(i) - '0';
arr[t].weight = 0.0;
++t;
}
}
}
void copy(Wt &a, Wt &b) {
a.num = b.num;
a.weight = b.weight;
}
void swap_(Wt &a, Wt &b) {
Wt temp;
copy(temp, a);
copy(a, b);
copy(b, temp);
}
void get_t_min(int first,int n) {
for (int i = first; i < n; i++) {
bool update = false;
for (int j = first; j < n-1; j++) {
if (arr[j].num > arr[j + 1].num) {//注意j+1的合法性
//建议手写优先
swap_(arr[j], arr[j+1]);
update = true;
}
}
if (!update) return;
}
}
int main() {
//data
int n = 0;
string str = "";
//input
cin >> n;
cin >> str;
get_arr(str);
//exe
int first = 0;
while (first < n-1) {
get_t_min(first,n);// 取得arr中first到n的最小的两个数,冒泡排序
/*check是否正确排序
for (int i = first; i < n; i++) {
cout << arr[i].num << " " << arr[i].weight << "**";
}
check("");
*/
int sum = arr[first].num+arr[first+1].num ;
double weight = (arr[first].num *(arr[first].weight+1)+
arr[first + 1].num*(arr[first+1].weight + 1))/sum;
first++;
arr[first].num = sum;
arr[first].weight = weight;
}
//output
cout << arr[first].num*arr[first].weight<< endl;
system("pause");
return 0;
}
2.2哈夫曼树的带权路径和=非叶子结点的和
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
using namespace std;
#define check(x) cout<<x<<endl
priority_queue<int, vector<int>, greater<int> > q;
void get_pq(string &str,int n) {
for (int i = 0; n!=0; ++i) {
if (str.at(i) != ',') {
//check(str.at(i) - '0');
q.push(str.at(i) - '0');
n--;
}
}
}
int main() {
//data
int n = 0;
string str = "";
//input
cin >> n;
cin >> str;
get_pq(str,n);
//exe
int sum = 0,min1=0,min2=0,i=0;
while (i<n-1) {
min1 = q.top(); q.pop();
min2 = q.top(); q.pop();
// cout << min1 << " " << min2 << endl;
sum += min1 + min2;
q.push(min1 + min2);
i++;
}
//output
cout << sum<< endl;
system("pause");
return 0;
}