問題描述:
在數據加密和數據壓縮中常須要對特殊的字符串進行編碼.給定的字母表A由26個小寫英文字母組成,即A={a,b...z}.該字母表產生的長序字符串是指定字符串中字母從左到右出現的次序與字母在字母表中出現的次序相同,且每一個字符最多出現1次.例如,a,b,ab,bc,xyz,等字符串是升序字符串.如今對字母表A產生的全部長度不超過6的升序字符串按照字典排列編碼以下:a(1),b(2),c(3).........,z(26),ab(27),ac(28),..................ios
對於任意長度不超過6的升序字符串,迅速計算出它在上述字典中的編碼.
算法設計:
對於給定的長度不超過6的升序字符串,計算它在上述字典中的編碼.
數據輸入:
輸出數據由文件名爲input.txt的文本文件提供.文件的第1行是一個正整數k,表示接下來共有k行,在接下來的k行中,每行給出一個字符串.
結果輸出:
將計算結果輸出到文件output.txt.文件共有k行,文件共有k行,每行對應於一個字符串的編碼.
輸入文件示例:
input.txt
2
a
b
輸出文件示例:
output.txt
1
2算法
#include <iostream> #include<fstream> using namespace std; //計算階乘 int factorial(int n) { if (n==0) { return 1; } int sum=1; for (int i=1;i<=n;i++) { sum*=i; } return sum; } //統計n位中取p位的狀況個數 int getnp(int p,int n) { int sum=1; for (int i=n-p+1;i<=n;i++) { sum*=i; } return sum/factorial(p); } //統計在總位數同樣的狀況下第p位前有多少 int getp(char a,int p,int n) { int sum = 0; for (int i = n+1;i<(a-'a'+1);i++) { sum += getnp(p-1,(26-i)); } return sum; } void main() { int sum=0; int size=0; char buffer[20]; ifstream inputfile("D:\\12.txt.txt"); ofstream outputfile("1-2out.txt"); while(!inputfile.eof()) { inputfile.getline(buffer,20); sum=0; size = strlen(buffer); for (int i=1;i<size;i++) { sum += getnp(i,26); sum += getp(buffer[i],size-i,buffer[i-1]-'a'+1); } sum += getp(buffer[0],size,0); sum++; outputfile<<sum<<"\n"; } outputfile.close(); }
如上代碼,思想爲,例如egh這樣的狀況,那咱們先把只有一位長的狀況和兩位長的加起來,即爲26C1和26C2,而後找出起始位爲a,b,c,d的三位單詞的狀況,它們也排在efg以前,即爲25C2,24C2,23C2,22C2(這裏須要注意並非26C2了,由於若是爲a開頭,那後面兩位只能從b之後的數開始選,即25個,b開頭的爲24個以此類推),而後考慮e開頭的,由於在上面的狀況事後就是高位以e開頭的狀況,這個時候須要注意,eah,ebh這樣的並不合理,因此咱們要將getp(buffer[i],size-i,buffer[i-1]-'a'+1),buffer[i]和buffer[i-1]進行比較即爲e和g進行比較而後經過比較只有ef爲開頭的才合理,而後咱們計算從efa到efz,繼而到最後一位因爲ega,egb這種不存在(經過buffer的比較可知),所以沒有其餘在eg開頭的狀況了,便是egh是eg開頭的三位數的第一種狀況,此時咱們的定位工做就完畢了。編碼