如果将五笔的编码按字典序排序,形成数组如下:a, aa, aaa, aaaa, aaab, aaac, ..., b, ba, baa, baaa, baab...yyyx, yyyy
其中a的索引是0,aa的索引是1,aaa的索引是2,aaaa的索引是3,以此类推:
1)、编写一个函数,输入是任意一个合法的字符串,输出这个字符串对应的索引;
2)、编写一个函数,输入是任意一个合法的索引,输出这个索引对应的字符串。
这道题最开始理解字典序列理解错了,字典序列中aaay后是aab,aayy后是ab,ayyy之后是b
可以想象一个树结构,第一层每个节点为1个字母,第二层每个节点为2个字母,以此类推。
1、观察头几个串:a-->0, aa->1, aaa->2,aaaa->3:应该可以看出来,这里的索引就是:字符串长度 - 1
2、已知a的索引,求b的索引:因为a到b之间隔了以下四种情况的字符串:a后跟2字符的串有25个(aa,ab,...ay),a后跟2字符的串 有25*25个(aaa, aab, ... ayy),a后面跟3字符的串有25*25*25个(aaaa,aaab,...ayyy),然后才是b,所以b的索引 = a的索引 + 25+25*25+25*25*25 + 1,加1是因为b排在a和中间的字符之后1个
3、已知aa的索引,求ab的索引:同理,ab的索引 = aa索引 + 25 + 25* 25 + 1
4、已知aaa的索引,求aab的索引:同理,aab的索引 = aaa索引 + 25 + 1
5、已知aaaa的索引,求aaab的索引 = aaaa索引 + 1
所以:可用一个权重数组来表示修正后的进制:factor[4] = {1+25+25*25+25*25*25, 1+25+25*25, 1+25, 1}
然后字符串string的索引函数为:index(string) = (string.length - 1) + sum[ factor[i] * (string[i] - 'a') , {i, 0, string.length-1 } ]
- int encode(char *str)
- {
- int a[]={1+25*25*25+25*25+25,1+25*25+25,1+25,1};
- int length=strlen(str);
- int index=0;
- for(int i=0;i<length;i++)
- {
- index+=(str[i]-'a')*a[i];
- }
- index+=length-1;
- return index;
- }
- void decode(char *str,int index)
- {
- int a[]={1+25*25*25+25*25+25,1+25*25+25,1+25,1};
- int i=0;
- while(index>=0)
- {
- *str='a'+index/a[i];
- index%=a[i];
- i++;
- str++;
- --index;
- }
- *str='\0';
- }
如果字典顺序换成a, b, ... x, y, aa, ab, ... yy, aaa, aab, ..., yyy, aaaa, aaab, ..., yyyy
这样就变简单了许多,可以类似按照26进制来算。
- int encode(char *str)
- {
- int length=strlen(str);
- int index=0;
- for(int i=0;i<length;i++)
- {
- if(i==length-1)
- index=index*25+str[i]-'a';
- else
- {
- index=index*25+(str[i]-'a'+1);
- }
- }
- return index;
- }
- void reverse(char *str)
- {
- int length=strlen(str);
- for(int i=0;i<length/2;i++)
- {
- char tmp=str[i];
- str[i]=str[length-1-i];
- str[length-1-i]=tmp;
- }
- }
- void decode(char *str,int index)
- {
- char *p=str;
- while(index>=0)
- {
- *p='a'+index%25;
- index/=25;
- p++;
- --index;
- }
- *p='\0';
- reverse(str);
- }