zoukankan      html  css  js  c++  java
  • 【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;
    	}
    
    }
  • 相关阅读:
    POJ 2175 Evacuation Plan 费用流 负圈定理
    POJ 2983 Is the Information Reliable? 差分约束
    codeforces 420B Online Meeting
    POJ 3181 Dollar Dayz DP
    POJ Ant Counting DP
    POJ 1742 Coins DP 01背包
    中国儒学史
    产品思维30讲
    Java多线程编程核心技术
    编写高质量代码:改善Java程序的151个建议
  • 原文地址:https://www.cnblogs.com/speedmancs/p/2073339.html
Copyright © 2011-2022 走看看