程序员面试金典——解题总结: 9.18高难度题 18.8给定一个字符串s和一个包含较短字符串的数组T,设计一个方法,根据T中的每一个较短字符串,对s进行搜索
来源:互联网 发布:cf推荐算法 编辑:程序博客网 时间:2024/05/15 15:00
#include <iostream>#include <stdio.h>#include <map>#include <vector>#include <string>using namespace std;/*问题:给定一个字符串s和一个包含较短字符串的数组T,设计一个方法,根据T中的每一个较短字符串,对s进行搜索分析:没明白什么意思,什么叫从数组中取出每个字符串,然后再另一个字符串中搜索。首先实现后缀树。后缀树含义:树中的每个顺着某个结点往下的结点路径所组成的字符串是原始字符串的后缀。 作用:进行后缀和子串匹配。 查询后缀树返回的结果:子子串在原始字符串中的起始位置,这个位置可能有多个。 实现原理: 生成后缀树:1设待查找字符串str,设其长度为n,分别遍历以第1个字符为起始字符的字符串,以第2个字符为起始的字符串,...,第n个字符为起始的字符串, 得到n个后缀字符串2对每个后缀字符串,将其首字符对应在字符串中位置存入集合中,并查找结点中是否有对应以当前后缀字符串第一个字符对应的子结点,如果有第一个字符对应的子节点(没有该子节点就新建一个),继续向下递归以该子节点来生成除首字符外的剩余字符串的后缀结点;查找某个字符串在后缀树中的起始位置: 查找字符串中首个字符,寻找到该字符在后缀树中的结点,利用该结点查找除首字符剩余字符串;如果在查找过程中某个字符没有对应结点,说明该子串不存在,直接返回;否则,找到该字符串最后一个字符对应的结点,返回该结点中存储的该子串的起始位置输入:4(查找字符串的个数n) mississippi(被查找的字符串)is sip hi sis(n个查找的字符串)输出:1 4(子串在字符串中起始位置,有多个就全部输出,没有就输出no) 6no3关键:1后缀树含义:树中的每个顺着某个结点往下的结点路径所组成的字符串是原始字符串的后缀。 作用:进行后缀和子串匹配。 查询后缀树返回的结果:子子串在原始字符串中的起始位置,这个位置可能有多个。2实现原理: 生成后缀树:1设待查找字符串str,设其长度为n,分别遍历以第1个字符为起始字符的字符串,以第2个字符为起始的字符串,...,第n个字符为起始的字符串, 得到n个后缀字符串2对每个后缀字符串,将其首字符对应在字符串中位置存入集合中,并查找结点中是否有对应以当前后缀字符串第一个字符对应的子结点,如果有第一个字符对应的子节点(没有该子节点就新建一个),继续向下递归以该子节点来生成除首字符外的剩余字符串的后缀结点;查找某个字符串在后缀树中的起始位置: 查找字符串中首个字符,寻找到该字符在后缀树中的结点,利用该结点查找除首字符剩余字符串;如果在查找过程中某个字符没有对应结点,说明该子串不存在,直接返回;否则,找到该字符串最后一个字符对应的结点,返回该结点中存储的该子串的起始位置*///后缀树结点:包含:结点对应的字符,该字符对应的子串在原始字符串中起始位置的集合,字符到结点的孩子结点映射 。 能够执行插入和返回子串下标,销毁的操作。class SuffixTreeNode{public:SuffixTreeNode(){}~SuffixTreeNode(){}void insertString(string& str , int index){_indexs.push_back(index);if(str.empty() || index < 0){return ;}char value = str[0];map<char , SuffixTreeNode*>::iterator it = _childs.find(value);SuffixTreeNode* child = NULL;if(it != _childs.end()){child = it->second;}//结点不存在,创建else{child = new SuffixTreeNode();_childs[value] = child;}//递归处理剩余字符串string sRemainder = str.substr(1);//第二个参数是长度:默认是从当前位置到结尾的长度,所以这里可以忽略child->insertString(sRemainder , index); // 子字符串和首字符的在原始字符串的起始位置相同}//返回str在原始字符串中的位置集合vector<int> getIndexs(string& str){//如果已经到达后缀树的叶子结点,说明查找到了该子串,返回叶子结点对应的子串在在原始字符串的位置集合(因为子串可能多次出现)if(str.empty()){return _indexs;}char value = str.at(0);map<char , SuffixTreeNode*>::iterator it = _childs.find(value);if(it != _childs.end()){//获取剩余字符串,对剩余字符串递归处理SuffixTreeNode* child = it->second;string remainder = str.substr(1);return child->getIndexs(remainder);}//如果当前字符在孩子结点中找不到,说明该子串无法找到,直接返回结果else{vector<int> results;return results;}}public:char _value;map<char , SuffixTreeNode*> _childs;vector<int> _indexs;};//后缀树包含一个根节点,能够返回查询子串的位置class SuffixTree{public:SuffixTree(string str){//如果是空字符串,就直接返回,不做任何处理if(str.empty()){cout << "String is empty." << endl;return ;}//创建根节点,并对字符串的所有后缀子串进行处理_root = new SuffixTreeNode();int length = str.length();string suffixStr;for(int i = 0 ; i < length ; i++){suffixStr = str.substr(i);_root->insertString(suffixStr , i);}}~SuffixTree(){deleteNode(_root);}vector<int> getIndexs(string str){return _root->getIndexs(str);}private://删除结点,析构,递归删除void deleteNode(SuffixTreeNode* root){map<char , SuffixTreeNode*>::iterator it;for(it = (root->_childs.begin()) ; it != (root->_childs.end()) ; it++){SuffixTreeNode* child = it->second;if(NULL != child){deleteNode(child);}}delete root;root = NULL;}public:SuffixTreeNode* _root;};void process(){int strNum;string searchStr;vector<string> strings;string value;while(cin >> strNum >> searchStr){strings.clear();for(int i = 0 ; i < strNum ; i++){cin >> value;strings.push_back(value);}SuffixTree suffixTree(searchStr);for(int i = 0 ; i < strNum ; i++){value = strings.at(i);vector<int> indexs = suffixTree.getIndexs(value);if(!indexs.empty()){int size = indexs.size();for(int j = 0 ; j < size ; j++ ){cout << indexs.at(j) << " ";}cout << endl;}else{cout << "no" << endl;}}}}int main(int argc , char* argv[]){process();getchar();return 0;}
0 0
- 程序员面试金典——解题总结: 9.18高难度题 18.8给定一个字符串s和一个包含较短字符串的数组T,设计一个方法,根据T中的每一个较短字符串,对s进行搜索
- 给一个字符串S和一个字符串数组T(T中的字符串要比S短许多),设计一个算法, 在字符串S中查找T中的字符串。
- 程序员面试金典——解题总结: 9.18高难度题 18.10给定两个字典里的单词,长度相等。编写一个方法,将一个单词变换成另一个单词,一次只改动一个字母。
- 程序员面试金典——解题总结: 9.18高难度题 18.11给定一个方阵,其中每个单元(像素)非黑即白。设计一个算法,找出四条边都是黑色像素的最大子方阵。
- 给定一个字符串s,请计算输出含有连续两个s作为子串的最短字符串。
- 程序员面试金典——解题总结: 9.18高难度题 18.13给定一份几百万个单词的清单,设计一个算法,创建由字母组成的最大矩形
- 将s所指字符串的反序和正序进行连接形成一个新串放在t所指的数组中
- 程序员面试金典——解题总结: 9.18高难度题 18.6设计一个算法,给定10亿数字,找出最小的100万个数字。假定计算机内存足以容纳全部10亿个数字。
- 程序员面试金典——解题总结: 9.18高难度题 18.7给定一组单词,编写一个程序,找出其中的最长单词,且该单词由这组单词中的其他单词组合而成。
- 程序员面试金典——解题总结: 9.18高难度题 18.12给定一个正整数和负整数组成的N*M矩阵,编写代码找出元素总和最大的子矩阵。
- 程序员面试金典——解题总结: 9.18高难度题 18.8---拓展: 实现一个Trie树
- 陈利人 面试题 给定两个字符串s和t(len(s)>len(t)),t可能是s的一个子序列。求所有s的子序列集合中,有多少个子序列等于t。
- 陈利人 面试题 给定两个字符串s和t(len(s)>len(t)),t可能是s的一个子序列。求所有s的子序列集合中,有多少个子序列等于t。
- 程序员面试金典——解题总结: 9.18高难度题 18.3编写一个方法,从大小为n的数组中随机选出m个整数。要求每个元素被选中的概率相同。
- 给定字符串S和字符串T,找到S中的最小窗口,其中将包含复杂度O(n)中T中的所有字符。
- 程序员面试金典——解题总结: 9.18高难度题 18.4编写一个方法,数出0到n(含)中数字2出现了几次
- 给定俩个字符串一个S(母串),一个T(子串),有多少种方法从母串中移除字符得到子字符串
- 给定一个字符串s和一个非空字符串p,找出s中所有p的字符串的起始索引。
- cocos2d-lua cc.CallFunc:create 带参数回调
- UVa442矩阵连乘
- venom结合Metasploit绕过360安全卫士
- PL/SqlDeveloper安装(Oracle11g服务安装完后客户端安装)
- ELF文件格式概述
- 程序员面试金典——解题总结: 9.18高难度题 18.8给定一个字符串s和一个包含较短字符串的数组T,设计一个方法,根据T中的每一个较短字符串,对s进行搜索
- C++ Qt Game Tutorial 5 - Adding Enemies
- 深挖SpringMVC_05_SpringMVC接收表单bean
- 珍爱网-一个套路深沉的网站
- (Mysql 二)Linux C语言显示mysql数据库中某个表的数据
- 自动安装服务
- ORACLE 数据库 ha 无法自动切换 asm 磁盘组没有自动mount
- *gcd(a,b)==a^b
- 5-9 Huffman Codes (30分)