2007-08-01

一个关于字符串操作的算法题

关键字: 算法 字符串 行程编码

最近在网上看到一道关于字符串操作的算法题,不过原题的表述以及给出的数据都有问题.这里我给出修正后的题目:

题目:设计一个方法 String encode(String str),对字符串str进行如下转换操作为一个新字符串:

         逐个扫描str的每个字符,

         1.若当前字符为'_',则添加"\UL"到新字符串; 否则:

         2.若当前字符表示一大于0的数字N,且该字符不是最后一个字符,则将后继字符添加N+1次到新字符串;否则:

         3.直接添加当前字符到新字符串.

         并且用一个字符'_'将相邻的变换隔开

         并设计一个String decode(String code)方法执行encode的逆操作,即将由encode(str)方法返回的字符串还原为str.

       encode方法的设计没有任何难度,只需要把题目"直译"成程序代码就OK了,有难度的地方在于decode方法.注意到字符串中的字符在encode之后的新字符串中是由'_'分开的,并且原字符串中的每个字符只由这个字符串变换后的字符串以及其后继字符有关,因此我们很容易可以想到先将编码后的字符串按'_'分解成一系列字符串,其中每个字符串对应原字符串的一个字符,然后从后向前一个个求出其所表示的字符.算法的大体想法就是这样,只有一点要注意:类似"4_"这种数字后跟'_'的情形会被编码成一列连续的"_____",应该区分出这种情形并加以处理.

       其实如果对压缩算法有所了解的话,很容易看出这个题目其实是行程编码(Run-Length Encoding)的一个变形.

下面给出本题的代码:

java 代码
  1. /**  
  2. *author: Eastsun  
  3. *version: 1.0 2007/8/1  
  4. */  
  5. import java.util.Scanner;   
  6. public class StringCode{   
  7.     public static void main(String[] args){   
  8.         Scanner s =new Scanner(System.in);   
  9.         while(true){   
  10.             String text =s.next();   
  11.             if("exit".equalsIgnoreCase(text)) break;   
  12.             String code =encode(text);   
  13.             boolean flags =true;       //用于检测decode是否正确工作的标记   
  14.             try{   
  15.                 if(!decode(code).equals(text)) flags =false;   
  16.             }catch(IllegalStateException e){   
  17.                 flags =false;   
  18.             }   
  19.             if(flags){   
  20.                 System.out.println("Code :" +code);   
  21.             }   
  22.             else{   
  23.                 System.out.println("Error code :" +code);   
  24.             }   
  25.         }   
  26.     }   
  27.     private static final String ESC_S = "\\UL";   
  28.     private static final char   ESC_C = '_';   
  29.        
  30.     /**  
  31.     *将编码后的字符串还原为原字符串  
  32.     *@throws IllegalStateException 如果参数str不是一个有效的编码字符串  
  33.     */  
  34.     public static String decode(String str)throws IllegalStateException{   
  35.         StringBuilder sb =new StringBuilder();   
  36.         char next =0xffff;   
  37.         int end =str.length(), start;   
  38.         while(end>0){   
  39.             if(next==ESC_C&&str.charAt(end-1)==ESC_C){   
  40.                 for(start =end -1;start>0&&str.charAt(start-1)==ESC_C;start--);   
  41.                 if(start!=0) start ++;   
  42.             }   
  43.             else{   
  44.                 start =str.lastIndexOf(ESC_C,end -1) +1;   
  45.             }   
  46.                
  47.             String code =str.substring(start,end);   
  48.                
  49.             if(code.equals(ESC_S)){   
  50.                 next = ESC_C;   
  51.             }   
  52.             else if(end-start==1){   
  53.                 next = code.charAt(0);   
  54.             }   
  55.             else{   
  56.                 for(int index =0;index
  57.                     if(code.charAt(index)!= next) throw new IllegalStateException("Illegal code: ["+start+","+end+"]");   
  58.                 next =(char)('0'+end-start-1);   
  59.             }   
  60.             sb.insert(0,next);   
  61.             end =start -1;   
  62.         }   
  63.         return sb.toString();   
  64.     }   
  65.        
  66.     /**  
  67.     * 将str编码为新的字符串  
  68.     */  
  69.     public static String encode(String str){   
  70.         StringBuilder sb =new StringBuilder();   
  71.         for(int index =0;index
  72.             char c =str.charAt(index);   
  73.                
  74.             if(c==ESC_C){   
  75.                 sb.append(ESC_S);   
  76.             }   
  77.             else if(c>'0'&&c<='9'&&index+1
  78.                 char next =str.charAt(index+1);   
  79.                 for(int count =c-'0';count>=0;count--)    
  80.                     sb.append(next);   
  81.             }   
  82.             else{   
  83.                 sb.append(c);   
  84.             }   
  85.                
  86.             if(index+1
  87.         }   
  88.         return sb.toString();   
  89.     }   
  90. }  
  • StringCode.rar (1.1 KB)
  • 描述: 本帖的代码打包
  • 下载次数: 43
评论
Eastsun 2007-08-03
这个是数字后面跟'_'的情形.
next ==ESC_C说明后继字符为'_',str.charAt(end-1)==ESC_C说明该字符为数字
leo_dream 2007-08-03
if(next==ESC_C&&str.charAt(end-1)==ESC_C){
for(start =end -1;start>0&&str.charAt(start-1)==ESC_C;start--);
if(start!=0) start ++;
}
这段代码是什么意思
Eastsun
搜索本博客
我的相册
1b680e5a-efae-3ec3-8ccd-970a4a72a056-thumb
6.5beta.PNG
共 61 张
最近加入圈子
存档
最新评论