【IT面试题007】英语字符串的分词程序
/* 给你一个没有间隔的字符串“thisisasentence”,如何将他分割成如下的句子:“this is a sentence”。 提供一个函数用来检验一个字符串是不是单词:bool dic(char* w); 完成下列的函数。要求效率尽可能快。 bool Detect(char* str) { } 尽量写出完整思路,最好有伪代码。 提示: 递归,回溯。这里使用最长单词优先匹配 + 深度优先搜索+回溯的方法解决此问题。 其中数据来源为一篇普通的英文文字,测试时大概有几千个英文单词,先进行预处理, 得到长字符串和单词词典。在实现时,由于使用的是stl的string,接口和题目中给出的有所处理, 但不影响解决该问题。本程序中 Go(str,startIdx) 意为对str(startIdx:)进行分词 而bool dic(char * w)其实就是程序中对词典map的find操作 */ #include "stdafx.h" #include <iostream> #include <string> #include <vector> #include <fstream> #include <map> using namespace std; int maxWordLen = 0; char puncs[] = {'.',',','-',')','(','[',']','\"'}; string splitResult[1000000]; bool bSuc = false; //已分的词的个数 int splittedWordNum = 0; map<string,int> wordDic; //判断是否是标点 bool isPunc(char ch) { for (int i = 0;i < sizeof(puncs);i++) { if (ch == puncs[i]) { return true; } } return false; } //从文件构造长字符串和词典 void ReadFromFile(const string & filePath,string& strSentence, map<string,int>& wordDic) { ifstream fin(filePath.c_str()); string str; string word; int wordOccured = 0; while (fin >> str) { int firstIdx = 0; while(firstIdx < str.size() && isPunc(str[firstIdx])) { firstIdx++; } int secIdx = str.size() - 1; while(secIdx >=0 && isPunc(str[secIdx])) { secIdx --; } if (secIdx >= firstIdx) { word = str.substr(firstIdx,secIdx - firstIdx + 1); wordDic[word] = 1; strSentence = strSentence + word; if (secIdx - firstIdx + 1 > maxWordLen) { maxWordLen = secIdx - firstIdx + 1; } wordOccured++; //cout << word << " "; } } cout << wordOccured << endl; fin.close(); } void PrintSplitResult() { for (int i = 0;i<splittedWordNum;i++) { cout << splitResult[i] << " "; } } void Go(string & strSentence,int startIdx) { //如果已经有分词成功,则结束 if (bSuc) { return; } //分词完毕 if (startIdx == strSentence.size()) { PrintSplitResult(); //cout << endl; //cout << splittedWordNum << endl; bSuc = true; return; } //否则从最长的词开始匹配 int maxLen = strSentence.size() - startIdx; if (maxLen > maxWordLen) { maxLen = maxWordLen; } for (int len = maxLen;len >0;len--) { string candidateWord = strSentence.substr(startIdx,len); //该词存在于词典 if (wordDic.find(candidateWord) != wordDic.end()) { splittedWordNum ++; splitResult[splittedWordNum - 1] = candidateWord; //递归对下标startIdx + len开头的字符串进行分词 Go(strSentence,startIdx + len); splittedWordNum --; // 这里需要回溯 } } } int _tmain(int argc, _TCHAR* argv[]) { string strSentence; string filePath = "file2.txt"; ReadFromFile(filePath,strSentence,wordDic); Go(strSentence,0); //cout << wordDic.size() << endl; //cout << splittedWordNum << endl; if (!bSuc) { cout << "分词失败!!" << endl; } }
posted on 2011-06-05 21:49 speedmancs 阅读(1056) 评论(0) 编辑 收藏 举报