Programming Pearls 笔记2

关于旋转字符串和回文

这个断断续续看了好长时间。

书中给了三种旋转字符串的方法

1.juggling

这个方法比较巧妙。

过程就是:假设x[] = “abcdefgh" 长度为8   从第3位开始。   即 n=8 ,i=3

执行下列交换

x[0]与x[0+i%n]  

x[0+i%n]与 x[0+2*i%n]   ……

每次都要模n.

一直到  再回到 x[0]为止。    即k*i%n==0的时候

注意:

如果没有完成全部交换,第二次就从x[1]开始   然后是,  x[1+i],x[1+2i]......

还是要模n.

整个过程进行     i和n  的最大公约数次     就可以完成字符串的旋转。     (why?  此处没想通)

这个问题,我至今没有想明白。。。。。

不知道 ,我把整个过程说清楚没有。。  我个人觉得原书上也没有说太清楚,可能自己英文水平还不够吧,自己琢磨好久才写代码来。

没看明白,即看代码吧。看过代码就清楚了。

自己实现的代码如下:

 1 void juggling (int i,int n,char *x)
2 {
3 int cycles=gcd(i,n);//最大公约数
4 int t;
5 for(int j=0;j<cycles;j++)
6 {
7 t=x[j];
8 int k=j;
9 do
10 {
11 x[k%n]=x[(k+i)%n];
12 k+=i;
13 }while(k%n!=j);
14 x[(k-i)%n]=t;
15 }
16 }


对比作者给出的代码如下:

 1 void jugglerot(int rotdist, int n)
2 { int cycles, i, j, k, t;
3 cycles = gcd(rotdist, n);
4 for (i = 0; i < cycles; i++) {
5 /* move i-th values of blocks */
6 t = x[i];
7 j = i;
8 for (;;) {
9 k = j + rotdist;
10 if (k >= n)
11 k -= n;
12 if (k == i)
13 break;
14 x[j] = x[k];
15 j = k;
16 }
17 x[j] = t;
18 }
19 }
20
21 void jugglerot2(int rotdist, int n)
22 { int cycles, i, j, k, t;
23 cycles = gcd(rotdist, n);
24 for (i = 0; i < cycles; i++) {
25 /* move i-th values of blocks */
26 t = x[i];
27 j = i;
28 for (;;) {
29 /* Replace with mod below
30 k = j + rotdist;
31 if (k >= n)
32 k -= n;
33 */
34 k = (j + rotdist) % n;
35 if (k == i)
36 break;
37 x[j] = x[k];
38 j = k;
39 }
40 x[j] = t;
41 }
42 }

 

2.块交换

这个方法的过程就是:

让 ab ==> ba  

先  a1a2b  (a1=b)    ==>   ba2a1  

然后想办法   a2a1  ==>   a1a2    明显递归进行就可以了。

这个方法本来想自己写出递归的程序。

然后是怎么也没写出来,不知道怎么控制条件

分析作者给出的代码。 

在某位网友的指点下,终于弄明白怎么回事情了。

 1 void gcdrot(int rotdist, int n)
2 { int i, j, p;
3 if (rotdist == 0 || rotdist == n)
4 return;
5 i = p = rotdist;
6 j = n - p;
7 while (i != j) {
8 /* invariant:
9 x[0 ..p-i ] is in final position
10 x[p-i..p-1 ] = a (to be swapped with b)
11 x[p ..p+j-1] = b (to be swapped with a)
12 x[p+j..n-1 ] in final position
13 */
14 if (i > j) {
15 swap(p-i, p, j);
16 i -= j;
17 } else {
18 swap(p-i, p+j-i, i);
19 j -= i;
20 }
21 }
22 swap(p-i, p, i);
23 }
24 /*这段代码里面。 i 和 j 始终代表 每次旋转 左边 和右边 字符串长度。 例如 abc|de i=3 j=2。 然后p 初始值为i 的初始值。
25 是为了 swap的时候定位。 最后,i 和 j 只能是 1 和 1 */
26
27 交换的代码如下:
28 void swap(int i, int j, int k) /* swap x[i..i+k-1] with x[j..j+k-1] */
29 { int t;
30 while (k-- > 0) {
31 t = x[i]; x[i] = x[j]; x[j] = t;
32 i++;
33 j++;
34 }
35
36 }
37 /*交换的时候也可以用 a=a+b;b=a-b;a=a-b的原理去做,效率更高*/

开始看。。完全不知道  i j p 是什么意思。。

但还是没有把它改成 递归的形式。。    功力还是不够啊。。

 

 

3.reverse

这个方法就比前面的 简单明了多了。。

原理就是:  ab ==>  ba

  1    arb

  2    arbr

  3    (arbr)r

这样就行了。

void reverse(int i,int j)
{
int t;
for(;i<j;)
{
t=x[i];x[i]=x[j];x[j]=t;
i++;
j--;
}
}
void swap(int i,int n)
{
reverse(0,i-1);//cbadefgh
reverse(i,n-1);//cbahgfed
reverse(0,n-1);//defghabc
}


简洁,明了。

 

 

 

还有一个思想就是回文。

快速找出回文词。

思路就是:

每个单词 打乱原来的顺序  

按照字母顺序重排  作为原来的sign

这样,只要是回文,就有同样的sign。

根据相同的sign   输出回文 就行了。

 

stop  tops  pots   都有相同的sign    "opst"

 

今天就到此吧。

读这种书真的很费劲。

坚持!

转载于:https://www.cnblogs.com/xibaohe/archive/2012/03/27/2419681.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值