问题描述:
1算法思路
- 编码=长度小于len的字符串个数+长度等于len,但在所给字符串之前的字符串个数
- 长度小于len的字符串个数=长度为1,2,3…len-1的升序字符串个数之和
- 长度为n的升序字符串个数 =分别以26个字母开头,长度为n的字符串个数之和
- 以i开头的、长度为n的升序字符串个数=以剩下字母依次开头,长度为n-1的升序字符串个数
2程序代码
#include<bits/stdc++.h>
using namespace std;
#include<windows.h>
#define N 10
int k;
char a[N];
//计算以begin开头的、长度为n的升序字符串个数
int s_1(int begin,int n){
int s=0;
if(n==1) return 1;
else{
for(int i=begin+1;i<=26;i++){
s+=s_1(i,n-1);
}
}
return s;
}
//计算长度为n的升序字符串个数
int s_2(int n){
int s=0;
for(int i=1;i<=26;i++){
s+=s_1(i,n);
}
}
int main()
{
freopen("input.txt","r",stdin);//输入数据由文件名为input.txt的文本文件提供
freopen("output.txt","w",stdout);//将计算结果输出到文件output.txt
//用于记录时间
LARGE_INTEGER nFreq,nBegin,nEnd;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBegin);
//算法核心代码如下
scanf("%d",&k);
while(k--){
scanf("%s",&a);
int ans=0;
int len=strlen(a);
//第一步:计算长度小于len的字符串个数
for(int i=1;i<len;i++){
ans+=s_2(i);
}
//第二步:加上长度等于len,但在所给字符串之前的字符串个数
int temp=0;
for(int i=0;i<len;i++){
int num=a[i]-'a'+1; //获取当前字符顺序号
int len_2=len-i; //获取当前字符串长度
for(int j=temp+1;j<num;j++){
ans+=s_1(j,len_2);
}
temp=num; //保证升序
}
printf("%d\n",ans+1);
}
fclose(stdin);
fclose(stdout);
QueryPerformanceCounter(&nEnd);
double t=(double)(nEnd.QuadPart-nBegin.QuadPart)/(double)nFreq.QuadPart;
printf("运行时间:%lf",t);
return 0;
}
3生成三种不同规模的测试数据:小、中、大(e.g.,几个、几百个、几万个甚至更多)
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
int count=10;
int main(){
freopen("input.txt","w",stdout);
printf("%d\n",count);
srand(time(0));
for(int j=0;j<count;j++)
{
int x=0,A=26,pre=0,n=6;
for(int i=1;i<=n && x!=26;i++){
x=rand()%A+1;
x=x+pre;
pre=x;
A=26-x;
printf("%c",'a'+x-1);
}
printf("\n");
}
fclose(stdout);
return 0;
}
4不同规模数据实验的时间对比
数据规模n | 10 | 1000 | 100000 |
---|---|---|---|
运行时间/s | 0.003512 | 0.628522 | 40.902037 |