打表法:碎片字符串,北京理工2019上机

1 问题描述

碎片字符串:形如aabbaaacaa的字符串,可分为五个相同连续字母组成的碎片:‘aa’,‘bb’,‘aaa’,‘c’,‘aa’,其中每个碎片只出现一次,即该字符串包含’aa’,‘bb’,‘aaa’,'c’四个碎片,且输出时按字典序排序。

输入:aaabbaaacaa 输出:
aa
aaa
bb
c

2 方法

模拟过程,每次把得到子串《字符,个数》放到一个二维数组里,各行按a~z索引,每一列记录子串长(保证不重复存入)
思想:先记录信息到一张表,再从表中取出数据
在这里插入图片描述

3 代码

#include <iostream>
#include <vector>
#include<string>
#include<algorithm>
using namespace std;

#define check(c) cout<<c<<endl
//name
typedef int TIMES;//同一个字符出现的次数
typedef pair<int, int> StrInfo;//first 行号 second 出现次数或者长度

class CounterOfstrs
{
public:
	CounterOfstrs(){}
	CounterOfstrs(string s):m_str(s) {
		
		//test func
	}
	~CounterOfstrs(){}

	void showAns() {
		int _Ptr_str=0;
		int size = m_str.size();

		while (_Ptr_str < size) {
			StrInfo _str_info;//放到循环里每次恢复为空
			readStrs(_Ptr_str,_str_info);
			writeTable(_str_info);
			++_Ptr_str;
		}
		printAns();
	}

	void readStrs(int &ptr, StrInfo &sInfo) {
		char _Now = m_str[ptr];
		sInfo.first = _Now - 'a';
		sInfo.second = ptr;

		while (ptr< m_str.size()&&m_str[ptr] == _Now) {
			ptr++;
		}

		sInfo.second = ptr-sInfo.second;
		ptr--;//恢复
	}

	void writeTable(StrInfo &sInfo) {
		int _Row_number = sInfo.first;
		int _Str_length	= sInfo.second;

		bool _Exist = find(m_lengtTable[_Row_number], _Str_length);
		if (!_Exist) {
			m_lengtTable[_Row_number].push_back(_Str_length);
		}
	}

	bool find(vector<TIMES>& strLens, int len) {
		bool _Exist = false;
		for (auto x : strLens) {
			if (x == len) {
				_Exist = true;
				break;
			}
		}
		return _Exist;
	}

	void printAns() {
		for (int i = 0; i < 27; i++) {
			int _Strlens_size = m_lengtTable[i].size();
			if (_Strlens_size != 0) {
				sort(m_lengtTable[i].begin(), m_lengtTable[i].end());
				for (int j = 0; j < _Strlens_size; j++) {
					showStr(i, m_lengtTable[i][j]);
				}
			}
		}
	}
	void showStr(int rowNumber, int len) {
		char _Now = rowNumber+'a';
		while (len--) {
			printf_s("%c", _Now);
		}
		printf_s("\n");
	}
private:
	vector<TIMES> m_lengtTable[27];
	string m_str;
};




int main() {
	CounterOfstrs ctest("aaasssbbbaassabbs");
	ctest.showAns();

	system("pause");
	return 0;
}

法二

借助数组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 (i < str.length()&&str[i] == str[i + 1]) {
			temp += str[i++];
		}
		set_str.insert(temp);//这一步是核心,将重复子串删除
	}

	//output
	for(string s: set_str) {
		cout << s << endl;
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值