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;
    	}
    
    }
  • 相关阅读:
    【ICLR2018】Mixup 解读
    MobileNetV2 解读
    MobileNetV1 解读
    AdaIN 解读
    心灵奇旅
    SA-Net: Shuffle Attention for Deep Convolutional Neural Networks
    ShuffleNet V1 解读
    情人节看《唐探3》
    拆弹人
    内卷常态下的就业烦恼
  • 原文地址:https://www.cnblogs.com/speedmancs/p/2073339.html
Copyright © 2011-2022 走看看