c++ 字母a~z升序排列编号 字典序问题 递归

探讨了在数据加密和压缩中对特定升序字符串进行字典序编码的方法,使用C++实现了一种递归算法,能够快速计算长度不超过6的升序字符串在字典中的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c++ 字母a~z升序排列编号 字典序问题 递归

互相学习,仅供参考,欢迎指正

**

字典序问题

**

问题描述:
***在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A由26个小写英文字母组成A={a,b,…,z}。该字母表产生的升序字符串是指字符串中字母按照从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1次。例如,a,b,ab,bc,xyz等字符串都是升序字符串。现在对字母表A产生的所有长度不超过6的升序字符串按照字典序排列并编码如下。

1 2 … 26 27 28 …
a b … z ab ac …
对于任意长度不超过6的升序字符串,迅速计算出它在上述字典中的编码。***

下面按照实验步骤解答
实验报告

  1. 问题分析:字典序问题,已知排序规则是位数少的排前面、相同位数按字母表序排列
    所以要求出某个升序字符串的位置,一种思路是把该字符串前面的数目相加
  2. 算法设计:(1)使用递归求出以第i位字母开头共有k位的字符串有多少
    (2)求出给出字符串所占位数m,把位数少于m的所有字符串相加
    (3)加上位数相同但首字符较小的
    (4)加上字符串中字母与其后面字母之间之间字母开头的m-i长度字符串的数量
    3.算法实现:
    f函数为2.(1)的实现
    Order为(2)(3)(4)的实现
    Judge判断是否为a~z升序字符串

5.运行结果图:
结果示意图

算法分析:算法逻辑并不难,把字符串之前的相加就行,需要知道哪些情况需要加上,以及通过递归实现
经验归纳:一步步分析,想法上不一定多么巧妙,难的是需要用代码来实现,以及递归的逻辑

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

int f(int i, int k) {
	int j;
	int sum = 0;
	if (k == 1) {
		return 1;
	}
	else {
		for (j = i + 1; j <= 26; j++) {
			sum += f(j, k - 1);
		}
	}
	return sum;
}//第i个字母开头长度为k的数量 

int order(string str)
{
	int sum = 1;//自己占一位
	//1.加上位数少于字符串的数量
	int i, j, len, h;
	len = str.length();
	for (i = 1; i < len; i++)
	{
		for (j = 1; j <= 26; j++)
		{
			sum += f(j, i);
		}
	}
	h = str[0] - 'a' + 1;//h为首位字符的位数
	//2.加上位数相同但首字符较小的
	for (i = 1; i < h; i++)
	{
		sum += f(i, len);
	}
	//3.再加上字符串中首字母相同长度相同排在前面的字符串的数量
	int count = h;
	for (i = 1; i < len; i++) {
		h = str[i] - 'a' + 1;
		len = len - i;
		for (j = count + 1; j < h; j++) {
			sum += f(j, len);
		}
		count = h;
	} 
	return sum;
}
//判断是否为a~z升序字符串
bool judge(string str)
{	int n = str.length(),i=0;
	for(i=0;i<n-1;i++)
	{//如果后面不比前面大则报错
		if (str[i] - str[i+1]>0)
		{
			return false;
		}
		if (str[i]<'a' || str[i]>'z')
		{
			return false;
		}
	}
	if (str[i]<'a' || str[i]>'z')
	{
		return false;
	}
	return true;
}
int main()
{
	ifstream infile("input.txt");
	ofstream outfile("output.txt");
	string s;
	stringstream ss;//通过字符流把字符串转换为数字
	int k;//表示有k个升序字符串
	if (!infile.is_open())
	{
		cout << "未成功打开文件"<<endl;
	}
	getline(infile,s);//读取一行,第一行即为数字k
	ss << s;
	ss >> k;
	while (getline(infile, s))
	{//读取字符串,判断编号
		if (judge(s))
		{
			cout << order(s) << endl;
			outfile << order(s) << endl;
		}
		else
		{
			cout << "字符串不是a~z升序" << endl;
			outfile << "字符串不是a~z升序"<<endl;
		}
	}
	infile.close();
	outfile.close();
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值