字典序問題(計算機算法與分析 1-2 王曉東)

問題描述:

在數據加密和數據壓縮中常需要對特殊的字符串進行編碼.給定的字母表A由26個小寫英文字母組成,即A={a,b...z}.該

字母表產生的長序字符串是指定字符串中字母從左到右出現的次序與字母在字母表中出現的次序相同,且每個字符最

多出現1次.例如,a,b,ab,bc,xyz,等字符串是升序字符串.現在對字母表A產生的所有長度不超過6的升序字符串按照字

典排列編碼如下:

1   2  3  ......26   27  28  ...

a  b   c  ......z      ab  ac ...

對於任意長度不超過6的升序字符串,迅速計算出它在上述字典中的編碼。

分析:

計算要分兩步:

給定一個字符串,假設有k位

<1>計算所有小於k位字符串的總和.

<2>計算等於k位,但是編碼小於它的總和

設以第i個字符打頭的長度k的升序字符串個數位f(i,k),長度k的升序字符串總個數爲g(k),則

g(k)=累加f(i,k),i從1到26

f(i,1)=1                                                                                  g(1)=累加f(i,1),i從1到26

f(i,2)=累加f(j,1)=26-i,j從i+1到26                                           g(2)=累加f(i,2)=累加(26-i),i從1到26

一般情況,有:

f(i,k)=累加f(j,k-1),j從i+1到26                                          

g(k)=累加f(i,k)=累加i(累加j,f(j,k-1)),i從1到26,j從i+1到26

代碼如下:

 

#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
int f(int i,int k)
{/*以第i個字符開頭,長度爲k的字符的升序字符個數*/
	int sum=0;
	if(k==1)
		return 1;
	for(int j=i+1;j<=26;j++)
		sum+=f(j,k-1);
	return sum;

}
int g(int k)
{//長度爲k的字符串長度
	int sum=0;
	for(int i=1;i<=26;i++)
	{
			sum+=f(i,k);

	}
	return sum;

}
int calculate(string s)
{
	int sum=0;
	int k=s.length ();
	for(int i=1;i<k;i++)
		sum+=g(i);
	int h=s[0]-'a'+1;;//第一個字母
	for(int i=1;i<h;i++)
		sum+=f(i,k);
	for(int i=1,temp=h;i<k;i++)
	{
		int n=s[i]-'a'+1;
		int length=k-i;//獲取此時的長度
		for(int j=temp+1;j<n;j++)
			sum+=f(j,length);
		temp=n;
	}
	return sum+1;


}
int _tmain(int argc, _TCHAR* argv[])
{
	string s;
	cin>>s;
	cout<<calculate(s);
	return 0;
}

發佈了25 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章