变位词问题





问题C
    给定一个英语词典,找出其中的所有变位词的集合。例如,“pots”、“stop”和“tops”互为变位词,因为每一个单词都可以通过改变其他单词中的字母的顺序来得到。
解答:
    最容易想到解决方法就是:对于每一个单词,找出其的所有排列,然后对词典进行遍历,如果其排序在词典中,那么此排序序列就是该词典中此单词的变位词。
    但是这种方法对于单词长度不是很长,且词典不是很大的时候,效率比较好;但是当单词变的很长,求其各个排列的时间、以及进行检索的时间将会很长,这种情况下,该方法不可取。

    那么,有没有一种比较效率比较高的方法呢?
    《编程珠玑》中给出一种效率比较高的方法,具体思路如下所示。
    (1)为每个单词生成一个标签,即对每个单词按字母序进行排序,这样使所有的变位词会有相同的标签;
    (2)根据标签对单词进行汇合,每个标签对应一个集合,这个集合包括其所有的变位词;
    每个单词的标签的生成:如上面所叙述的那样,把这个单词所包含的字母,按照字母序进行排序。这就可以使所有的变位词的标签就全相等了。

    下面是我实现这个程序的详细过程,记录下来,以进行交流和学习。
    (1)词典的获取
    为了获取词典,从网上随意的下载了一篇英语文章,然后进行相应的处理,从而获取了词典。
    在对文章进行处理的过程中,这里去除了标点符号等简单字符,同时也进行了去除重复。
    从网上获取的文章如下所示。
    
    
    (2)获取“标签 单词”
     通过对获取的文章进行处理,去除掉标点符号等以及去除重复过,然后对各个单词进行排序,进而获取了相应单词的“标签”,我们把标签和单词以“标签  单词”的格式保存到文件中。
    保存内容如下所示。
    

    (3)获取变位词集合
    获取变位词集合的方法同《编程珠玑》上讲述的类似,获取的内容如下所示。  
    

    
    完成的程序代码如下所示。

  1. /*
  2.  *        Author:梦醒潇湘
  3.  *         Date :2013/6/9/19:55
  4.  *        Place :Hit
  5.  *        Email :9974771**@qq.com
  6.  */
  7. #include <iostream>
  8. #include <set>
  9. #include <stdio.h>
  10. #include <sys/stat.h>
  11. #include <fstream>
  12. #include <map>

  13. using namespace std;

  14. #define SOURCEFILE "big.txt" //原文件,就是小说的一部分,为了抽取单词
  15. #define DESTFILE "dict.txt"     //形成的词典 标签 单词
  16. #define RESULTFILE "result.txt" //结果文件
  17. #define MAXNUM 100             //单词的最大长度
  18. #define DEBUG

  19. set<string> dict;                 //保存处理好的字典

  20. //需要删除的字符
  21. const char delim[] = ".,:;`'/"+-_(){}[]<>*&^%$#@!?~/|=1234567890 tn";

  22. /*
  23.  * 函数功能:将字符串中的字符串全部转化为小写
  24.  * 返回值 :转换后的字符串指针
  25.  * 参数 :
  26.  *    @prama *word 指向源字符串的指针
  27.  */
  28. static char *strtolower(char *word)
  29. {
  30.     char *s;
  31.     if(word == NULL)
  32.     {
  33.         return NULL;
  34.     }
  35.     for(s = word; *s != ''; s++)
  36.     {
  37.         *s = tolower(*s);
  38.     }

  39.     return word;
  40. }

  41. /*
  42.  * 函数功能:读取文件中的关键字
  43.  * 返回值 :转化成功返回1;反之,返回0
  44.  * 参数 :
  45.  * @prama 无
  46.  */
  47. static int read_file()
  48. {
  49.     char *file, *word, *w;
  50.     FILE *fp = fopen(SOURCEFILE, "r");
  51.     struct stat sb;

  52.     if(!fp)
  53.     {
  54.         return 0;
  55.     }

  56.     if(stat(SOURCEFILE, &sb))
  57.     {
  58.         return 0;
  59.     }
  60.     
  61.     file = (char *)malloc(sb.st_size);
  62.     if(!file)
  63.     {
  64.         fclose(fp);
  65.         return 0;
  66.     }

  67.     fread(file, sizeof(char), sb.st_size, fp);

  68.     word = strtok(file, delim);
  69.     while(word != NULL)
  70.     {
  71.         w = strtolower(strdup(word));

  72.         string str = w;
  73.         dict.insert(str);
  74.         
  75.         word = strtok(NULL, delim);
  76.     }

  77.     free(file);
  78.     fclose(fp);

  79.     return 1;
  80. }

  81. /*
  82.  * 函数功能:用于qsort()函数
  83.  */
  84. int comp(const void *a, const void *b)
  85. {
  86.     return *(char *)a - *(char *)b;
  87. }

  88. /*
  89.  * 函数功能:将字典中的单词保存到文件中, 并且把标签给求解出来
  90.  * 返回值 :保存成功,返1;反之,则返回0
  91.  * 参数 :
  92.  *     @prama 无
  93.  *        
  94.  *        保存格式:标签 单词
  95.  *                 标签 单词
  96.  *                 .... ....
  97.  */
  98. int SaveToFile()
  99. {
  100.     FILE *out;
  101.     out = fopen(DESTFILE, "w");
  102.     if(out == NULL)
  103.     {
  104.         cout << "fopen() error in SaveToFile()." << endl;
  105.         return 0;
  106.     }

  107.     set::iterator iter = dict.begin();
  108.     for( ; iter != dict.end(); iter++)
  109.     {
  110.         char tmpone[MAXNUM] = {''};
  111.         char tmptwo[MAXNUM] = {''};

  112.         strncpy(tmpone, (*iter).c_str(), MAXNUM);
  113.         strncpy(tmptwo, (*iter).c_str(), MAXNUM);
  114.                 
  115.         qsort(tmpone, strlen(tmpone), sizeof(char), comp);
  116.         
  117.         #ifdef DEBUG        
  118.             cout << tmpone << " "<< *iter << endl;
  119.         #endif

  120.         fprintf(out, "%%sn", tmpone, tmptwo);
  121.     }

  122.     fclose(out);
  123.     
  124.     cout << "字典保存到文件成功." << endl;
  125.     return 1;
  126. }

  127. /*
  128.  * 函数功能:读取保存好的字典文件,进行压缩,获取最终的结果
  129.  * 返回值 :读取成功,返回1;反之,返回0
  130.  * 参数 :
  131.  *     @prama 无
  132.  */
  133. int squasd()
  134. {
  135.     /*
  136.     ifstream infile(DESTFILE, ios::in);
  137.     ofstream outfile("Result.txt",ios::out);
  138.     //assert(infile);
  139.     //assert(outfile);
  140.     if(infile == NULL || outfile == NULL)
  141.     {
  142.         return 0;
  143.     }
  144.     
  145.     string sig, word;
  146.     string sigone, wordone;
  147.     infile >> sig >> word;
  148.     outfile << sig << " " << word;
  149.     while(infile >> sigone >> wordone)
  150.     {
  151.         if(strcmp(sigone.c_str(), sig.c_str()) == 0)
  152.         {
  153.             if(strcmp(wordone.c_str(), word.c_str()) == 0)
  154.             {
  155.                 //the same word
  156.                 continue;
  157.             }
  158.             else
  159.             {
  160.                 outfile << " " << wordone;
  161.             }    
  162.         }
  163.         else
  164.         {
  165.             outfile << endl;
  166.             outfile << sigone << " " << wordone;
  167.             sig = sigone;
  168.             word = wordone;
  169.         }
  170.     }
  171.     infile.close();
  172.     outfile.close();
  173.     cout << "处理完毕." << endl;
  174.     return 1;
  175.     */
  176.     //打开dict.txt文件
  177.     ifstream infile(DESTFILE, ios::in);
  178.     if(infile == NULL)
  179.     {
  180.         return 0;
  181.     }
  182.     
  183.     //读取文件内容,保存到multimap中
  184.     multimap res;
  185.     string sig, word;
  186.     while(infile >> sig >> word)
  187.     {
  188.         res.insert(make_pair(sig, word));
  189.     }

  190.     //打开保存最终结果的文件
  191.     ofstream outfile(RESULTFILE, ios::out);
  192.     if(outfile == NULL)
  193.     {
  194.         return 0;
  195.     }
  196.     
  197.     //进行处理
  198.     multimap::iterator iter = res.begin();
  199.     if(iter == res.end())
  200.     {        
  201.         return 0;
  202.     }
  203.     outfile << iter->first << " " << iter->second;
  204.     iter++;
  205.     
  206.     sig = iter->first;
  207.     word = iter->second;

  208.     for( ; iter != res.end(); iter++)
  209.     {
  210.         char tmpone[MAXNUM] = {''};
  211.         char tmptwo[MAXNUM] = {''};
  212.         
  213.         strncpy(tmpone, (iter->first).c_str(), MAXNUM);
  214.         strncpy(tmptwo, (iter->second).c_str(), MAXNUM);
  215.     
  216.         if(strcmp(sig.c_str(), tmpone) == 0)
  217.         {
  218.             if(strcmp(word.c_str(), tmptwo) == 0)
  219.             {
  220.                 //same word here
  221.                 continue;
  222.             }
  223.             else
  224.             {
  225.                 outfile << " " << tmptwo;
  226.             }
  227.         }
  228.         else
  229.         {
  230.             outfile << endl;
  231.             outfile << tmpone << " " << tmptwo;
  232.             sig = tmpone;
  233.             word = tmptwo;
  234.         }
  235.     }
  236.     infile.close();
  237.     outfile.close();
  238. }
  239. int main()
  240. {
  241.     //读取文件,创建词典
  242.     if(!read_file())
  243.     {
  244.         return EXIT_FAILURE;
  245.     }
  246.     //保存字典到文件中
  247.     if(!SaveToFile())
  248.     {
  249.         return EXIT_FAILURE;
  250.     }
  251.     //进行最后结果的出来
  252.     if(!squasd())
  253.     {
  254.         return EXIT_FAILURE:
  255.     }
  256.     return EXIT_SUCCESS;
  257. }
  258. //上面的代码在粘贴的时候可能会有错误,附件为文件。






链接:http://blog.chinaunix.net/uid-26548237-id-3761073.html




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值