Chinaunix首页 | 论坛 | 博客
  • 博客访问: 56053
  • 博文数量: 16
  • 博客积分: 650
  • 博客等级: 上士
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-08 19:32
文章分类

全部博文(16)

文章存档

2008年(16)

我的朋友
最近访客

分类: C/C++

2008-06-16 21:00:42

还是深信服笔试题:要求在s1中删除所有s2的字符,要用最快的算法。
 
最正常最普通思想就是先申请一个s1长度的空间temp,两次for循环,遍历s1的字符时,再遍历s2,是否在s2中找到,找到则跳出继续遍历s1,找不到则写到temp里;显然这个算法效率比较差;
 
主要因为在s2中可能有多个字符重复,这样对同个字符遍历了多次;同时s1中也有相同字符的话,那么这个遍历的次数就呈指数增长。
 
下面的思想就是不管s2长度多少,组长的字符是个有限的小集合;首先遍历s2找出这个小集合,然后遍历s1,看字符是否在小集合中;
 
对于是否在小集合中用下面方法非常快捷:
由于每个字符对应唯一asc码,就是一个整数,用类似于FD_SET的东东。譬如整数0-31,对应数组a[0],
a[0]占32位,00000000000000000000000000000000,假如如果找到s2中asc码为31的字符,则将第32位置为1 00000000000000000000000000000001,然后遍历s1时,发现某个字符对应的标志位设置位1了说明s1有这个字符,跳过即可。说白了,这就是个hash的过程,只是所有字符对应整数唯一,不比再解决冲突问题。(这招在《编程珠玑》里学到的,嗷嗷有用)
 

#include <stdio.h>
#include <string.h>
#include <time.h>

#define SHIFT 5
#define NUM 1000
#define MASK 0x1f
#define BIT 32

int a[1 + NUM/BIT] = {0};

void set(int i)
{
    a[i>>SHIFT] |= (1 << (i & MASK));
}

void init(int i)
{
    a[i>>SHIFT] &= ~(1 << (i & MASK));
}

int test(int i)
{
    int k;
    k = a[i>>SHIFT] & (1 << (i & MASK));
    return k;
}

void S1_S2(char* pc1, char* pc2)
{
    char* pTemp1 = pc1;
    char* pTemp2 = pc2;

    while(*pTemp2 != '\0')
    {
        set((int)*pTemp2);
        pTemp2++;
    }

    while(*pTemp1 != '\0')
    {
        if(!test(*pTemp1))
        {
            printf("%c", *pTemp1);
        }
        pTemp1++;
    }

    printf("\n");
}

void main()
{
    char c1[] = "abcdefghijklmnopqrstuvwxyz";
    char c2[] = "acefhj";
    S1_S2(c1, c2);
}

上面是详细代码,主要处理函数就是S1_S2,

阅读(1362) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~