变位词的查找(下)

本文也同步发表在我的公众号“我的天空

 

实现方案优劣的思考

 

之前我们的实现方案的优点是一旦目标词库的签名建立后,则变位词的查找会变得简单而快速;缺点是由于在生成目标词库时,要为每个词都生成签名,导致生成词库的时间会变慢,同时会消耗空间。对于那些没有被查找到的字符串的签名实际上是浪费的。

 

测试结果:在CPU为Inter Core i3-2328M,内存为6GB的PC上生成数量为1万的目标词库平均时间为377毫秒,查找变位词的平均时间为11毫秒。

 

第二种方案

 

在生成目标词库的时候并不生成签名,而是在查找的时候生成签名。

 

function search(str){
   var mathstr="";
   for(var x in array_str){
       //查找时生成签名,再判断签名是否相同
       if(get_sign(str)==get_sign(array_str[x])){
           mathstr+=mathstr.length==0?array_str[x]:","+array_str[x];
       }
   }
    return mathstr;  //返回找到的变位词

}

 

测试结果:生成数量为1万的目标词库平均时间为130毫秒,查找变位词的平均时间为530毫秒

 

该方案虽然提高了生成目标词库的速度,并节省空间,但是查找的速度太慢,与第一种方案相比较慢了约50倍。分析代码发现每次查找都需要为目标词库重新建立一遍签名,效率太过低下,考虑优化。

 

第二种方案的优化

 

针对第二种方案的不足之处,考虑做如下优化:如果两个词互为换位词,那么这两个词的长度必定相同,同时组成这两个词的字母的asscii编码之和也必定相同,因此在遍历目标词库时,首先判定这两个条件,如果满足则再获取其签名来作比较。获取字母的ascii编码采用charCodeAt()函数。

 

function search(str){
    var mathstr="";
    for(var x in array_str){
        //如果两个词互为变位词,那么这两个词的长度和各字母的asciicode之和必须相同
        if(str.length==array_str[x].length && get_asciicode_total(str)==get_asciicode_total(array_str[x])){
            //查找时判断签名是否相同
            if(get_sign(str)==get_sign(array_str[x])){
                mathstr+=mathstr.length==0?array_str[x]:","+array_str[x];
            }
        }
    }
    return mathstr;
}
     
 //获得字符串的ascii码之和
function get_asciicode_total(str){
    var data=str.split("");
    var i=0;
    for(var x in data){
        i+=data[x].charCodeAt();
    }
    return i;

 

经测试,优化后的查找速度平均为43毫秒,速度提升还是很有效果的!

 

总结

 

该题主要是偏向于对问题的思考、解决方案的制定、实现与选择、代码优化等方面,在实际工作中,往往一个问题的解决会有多套方案,大家应该学会从各方面来衡量、测试,最终选择解决的问题的最优方案。该题主要涉及到随机数的操作、排序算法的掌握、ascii编码的掌握。

 

当然,以上两种方案仍有优化的空间,对于第一种,可以考虑将签名数组按照签名来排序,这样就无需每次都遍历整个签名数组,如果生成的目标词库数量巨大,还可以考虑将签名数组分段索引,以便能更快的找到签名;对于第二种,可以将查找中已生成的签名保存下来,这样下次查找再遇到该字符串该就无需再生成签名了,因为在整个程序中,最影响性能的就是生成签名,我们应尽量减少生成签名的操作。

 

示例代码

https://github.com/panyongwow/anagram

转载于:https://www.cnblogs.com/mysky7511/p/6682108.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
优化改进以下代码#include <iostream> #include <fstream> #include <string> #include <vector> #include <algorithm> #include <iterator> using namespace std; typedef istream_iterator<string> string_input; void welcome() { cout << "******************* 变位词查找系统*********************\n" << "在词典找出给定的字符串的所有变位词" << endl; } void readDict(vector<string> & dictionary) { cout << "首先,请输入词典的文件名称:" << endl; string dictionary_name; cin >> dictionary_name; ifstream ifs(dictionary_name.c_str()); if (!ifs.is_open()) { cerr << "异常:文件"<< dictionary_name << "没有找到 " << endl; exit(1); } cout << "词典读入 ..." << flush; copy(string_input(ifs), string_input(), back_inserter(dictionary)); sort(dictionary.begin(),dictionary.end()); cout << "词典包含有 " << dictionary.size() << " 个单词\n\n"; ifs.close(); } void analyseAnagram(const vector<string> & dictionary) { cout << "请输入单词(或任意字母序列)" << endl; for (string_input p(cin); p != string_input(); ++p) { cout << "查找输入单词的变位词..." << endl; string word = *p; sort(word.begin(), word.end()); bool found_one = false; do { if (binary_search(dictionary.begin(), dictionary.end(), word)) { cout << " " << word ; found_one = true; } } while (next_permutation(word.begin(), word.end())); if (!found_one) cout << " 抱歉,没有找到变位词\n"; cout << "\n请输入下一个单词 " << "(或输入Ctrl+Z终止程序 ) \n" << endl; } } int main() { welcome(); vector<string> dictionary; readDict(dictionary); analyseAnagram(dictionary); system("pause"); return 0; }
最新发布
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值