字符串压缩问题 字符串压缩问题——程序员解法 字符串压缩问题——程序员解法

字符串压缩问题
字符串压缩问题——程序员解法
字符串压缩问题——程序员解法

字符串压缩问题——程序员解法

 

  在http://www.cnblogs.com/bestDavid/p/Stringeliminate.html看到了一个有趣的小题:

给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它。
如有ab或ba连续出现,你把它们替换为字母c;
有ac或ca连续出现时,你可以把它们替换为字母b;
有bc或cb连续出现时,你可以把它们替换为字母a。
你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的最短长度。
输入:字符串。长度不超过200,仅由abc三种小写字母组成。
输出:按照上述规则不断消除替换,所得到的字符串最短的长度。
例如:
输入cab,输出2。因为我们可以把它变为bb或者变为cc。          
输入bcab,输出1。尽管我们可以把它变为aab -> ac -> b,也可以把它变为bbb,但因为前者长度更短,所以输出1。

  这个题目原博文中是用“数学”的方法给出解答的,但其推理证明过程(包括引文给出的证明过程)并不严谨,结论依据不足。所以这里用程序员的思考方法给出解答。

  程序员的方法无非就是老老实实地进行替换。对每一种可以替换的情形都进行替换。例如对bcab,可以替换为aab,bbb和bcc。题中提到“可以不断反复按照这个规则进行替换”,所以上面的各个情况又可以进一步
  aab:
  aab->ac->b 长度为1.
  bbb:
  无不同字母,无法进一步替换。长度为3
  bcc:
  bcc->ac->b 长度为1
  综上,对bcab进行不断变换,所得到的字符串的最短长度为1。
  因此,很容易给出代码总体结构。 

字符串压缩问题
字符串压缩问题——程序员解法
字符串压缩问题——程序员解法
 1 #include <stdio.h>
 2 
 3 #define MAX 200
 4 
 5 typedef char String[ MAX + 1 ];
 6 
 7 #define N(x) N_(x)
 8 #define N_(x) #x
 9 
10 void input( char * );
11 unsigned min_len( char * );
12 
13 int main( void )
14 {
15    String str;  
16    
17    input( str );
18 
19    printf("替换最终结果的最短长度为%u。
" , min_len( str ) );
20 
21    return 0;
22 }
23 
24 unsigned min_len( char *s )
25 {
26    
27 }
28 
29 void input( char *s )
30 {
31    puts("输入字符串");
32    scanf("%"N(MAX)"[abc]s",s);
33    puts("要确定长度的字符串为:");
34    puts( s );
35 }
字符串压缩问题
字符串压缩问题——程序员解法
字符串压缩问题——程序员解法

   其中宏 MAX 为字符串初始最大长度,为了给字符串结尾的 留出空间,存储字符串的字符数组的最大尺寸为 MAX + 1 。由于这种类型在整个代码中频繁用到,所以用 typedef 为其取了一个统一的名字。
  函数input()输入字符串由于字符串由a、b、c三种字母组成,所以禁止输入其他字符这就是 scanf("%"N(MAX)"[abc]s",s); 中[abc]的目的。又考虑到防止数组输入越界,因此为输入增加了宽度限制——N(MAX),宏展开后的结果为"200"。所以"%"N(MAX)"[abc]s"就是"%200[abc]s"。

  下面考虑min_len( char *s )函数。基本思路就是先求出s的初始长度

int len = strlen( s );

  然后从头至尾检查是否有相邻的相异字符,如有则替换:

reduce( newstr , s , i1 );

  这样将得到一个新的字符串newstr。设新字符串的长度为

int newlen ;

  新字符串最终长度显然仍然可以用min_len()求得:

newlen = min_len( newstr );

  如果newlen小于len,则将len记为newlen的值。

         if ( newlen < len )
         {
            len = newlen ;
         }

  这样返回最后的len就是变换后的最短长度。min_len函数完整代码如下:

字符串压缩问题
字符串压缩问题——程序员解法
字符串压缩问题——程序员解法
 1 unsigned min_len( char *s )
 2 {
 3    int len = strlen( s );
 4    int i = 0 ;
 5    while ( s[i] != '

  在http://www.cnblogs.com/bestDavid/p/Stringeliminate.html看到了一个有趣的小题:

给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它。
如有ab或ba连续出现,你把它们替换为字母c;
有ac或ca连续出现时,你可以把它们替换为字母b;
有bc或cb连续出现时,你可以把它们替换为字母a。
你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的最短长度。
输入:字符串。长度不超过200,仅由abc三种小写字母组成。
输出:按照上述规则不断消除替换,所得到的字符串最短的长度。
例如:
输入cab,输出2。因为我们可以把它变为bb或者变为cc。          
输入bcab,输出1。尽管我们可以把它变为aab -> ac -> b,也可以把它变为bbb,但因为前者长度更短,所以输出1。

  这个题目原博文中是用“数学”的方法给出解答的,但其推理证明过程(包括引文给出的证明过程)并不严谨,结论依据不足。所以这里用程序员的思考方法给出解答。

  程序员的方法无非就是老老实实地进行替换。对每一种可以替换的情形都进行替换。例如对bcab,可以替换为aab,bbb和bcc。题中提到“可以不断反复按照这个规则进行替换”,所以上面的各个情况又可以进一步
  aab:
  aab->ac->b 长度为1.
  bbb:
  无不同字母,无法进一步替换。长度为3
  bcc:
  bcc->ac->b 长度为1
  综上,对bcab进行不断变换,所得到的字符串的最短长度为1。
  因此,很容易给出代码总体结构。 

字符串压缩问题
字符串压缩问题——程序员解法
字符串压缩问题——程序员解法
 1 #include <stdio.h>
 2 
 3 #define MAX 200
 4 
 5 typedef char String[ MAX + 1 ];
 6 
 7 #define N(x) N_(x)
 8 #define N_(x) #x
 9 
10 void input( char * );
11 unsigned min_len( char * );
12 
13 int main( void )
14 {
15    String str;  
16    
17    input( str );
18 
19    printf("替换最终结果的最短长度为%u。
" , min_len( str ) );
20 
21    return 0;
22 }
23 
24 unsigned min_len( char *s )
25 {
26    
27 }
28 
29 void input( char *s )
30 {
31    puts("输入字符串");
32    scanf("%"N(MAX)"[abc]s",s);
33    puts("要确定长度的字符串为:");
34    puts( s );
35 }
字符串压缩问题
字符串压缩问题——程序员解法
字符串压缩问题——程序员解法

   其中宏 MAX 为字符串初始最大长度,为了给字符串结尾的 留出空间,存储字符串的字符数组的最大尺寸为 MAX + 1 。由于这种类型在整个代码中频繁用到,所以用 typedef 为其取了一个统一的名字。
  函数input()输入字符串由于字符串由a、b、c三种字母组成,所以禁止输入其他字符这就是 scanf("%"N(MAX)"[abc]s",s); 中[abc]的目的。又考虑到防止数组输入越界,因此为输入增加了宽度限制——N(MAX),宏展开后的结果为"200"。所以"%"N(MAX)"[abc]s"就是"%200[abc]s"。

  下面考虑min_len( char *s )函数。基本思路就是先求出s的初始长度

int len = strlen( s );

  然后从头至尾检查是否有相邻的相异字符,如有则替换:

reduce( newstr , s , i1 );

  这样将得到一个新的字符串newstr。设新字符串的长度为

int newlen ;

  新字符串最终长度显然仍然可以用min_len()求得:

newlen = min_len( newstr );

  如果newlen小于len,则将len记为newlen的值。

         if ( newlen < len )
         {
            len = newlen ;
         }

  这样返回最后的len就是变换后的最短长度。min_len函数完整代码如下:

字符串压缩问题
字符串压缩问题——程序员解法
字符串压缩问题——程序员解法
 1 unsigned min_len( char *s )
 2 {
 3    int len = strlen( s );
 4    int i = 0 ;
 5    while ( s[i] != '