字典序問題(計算機演算法與分析 1-2 王曉東)
阿新 • • 發佈:2019-01-05
問題描述:
在資料加密和資料壓縮中常需要對特殊的字串進行編碼.給定的字母表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; }