题1:输入两个字符串,比如abdbcc和abc,输出第二个字符串在第一个字符串中的连接次序。即输出125,146,145,146。【美国著名数据分析软件企业SA公司2008年面试题】
解析:本题算法是先找到第二个字符串中各个字符分别出现的位置,利用其位置构造多叉树(构造规则为子节点必须比父节点大)。遍历构造完成的多叉树即相应的组合。
例子中搜索到a、b、c在源字符串中出现的位置序列分别为{1}、{2,4}、{5,6}。
1
2 4 //在第二个序列中取值
5 6 5 6 //在第三个序列中取值
然后将算法组合成125、146、145、146。
答案:
// P83_example1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
//#include <stdio.h>
#include <string.h>
void PrintfArray(char* p_str, //父字符串
char* s_str, //子字符串
int* print_arr, //存放序列的数组
int p_len, //父字符串长度
int s_len, //子字符串长度
int print_arr_num, //序列数组元素的个数
int p_start_num, //父字符串开始的遍历位置
int s_start_num) //子字符串开始的遍历位置
{
int pStartnum = p_start_num; //记录父字符串遍历开始的位置
int sStartnum = s_start_num; //记录子字符串遍历开始的位置
int printNum = print_arr_num; //数组中保存的元素个数
//退出递归的条件:序列数组元素的个数等于子字符串的长度,说明子字符串在父字符串中出现了一次,打印
if(printNum == s_len)
{
for(int i = 0; i < s_len; ++i)
{
std::cout<<*(print_arr + i);
}
std::cout<<std::endl;
return;
}
//同时遍历父子字符串,每次从pStartnum和sStartnum位置开始
for(int i = pStartnum; i < p_len; ++i)
{
for(int j = sStartnum; j < s_len; ++j)
{
//如果两个位置的字符相同,则下次遍历的开始位置同时向后移动一位
if(*(p_str + i) == *(s_str + j))
{
print_arr[printNum] = i + 1;
pStartnum = i;
sStartnum = j;
PrintfArray(p_str, s_str, print_arr, p_len, s_len, printNum + 1, pStartnum + 1, sStartnum + 1); //递归
}
}
}
}
//连接序列
void ConnectSequence(char* p_str,
char* s_str)
{
int p_len = strlen(p_str); //第一个字符串的长度
int s_len = strlen(s_str); //第二个字符串的长度
int* print_arr = new int[s_len]; //申请一个s_len长度的整型数组,用于记录其位置
unsigned int print_arr_num = 0; //数组中元素个数
//如果两个字符串都为空,则退出
if(NULL == p_str && NULL == s_str)
{
std::cout<<"string error"<<std::endl;
return;
}
//内存申请失败
if(NULL == print_arr)
{
std::cout<<"allocate error"<<std::endl;
return;
}
PrintfArray(p_str, s_str, print_arr, p_len, s_len, 0, 0, 0);
}
int _tmain(int argc, _TCHAR* argv[])
{
char ParString[] = "abdbcc"; //第一个字符串
char SonString[] = "abc"; //第二个字符串
ConnectSequence(ParString, SonString); //打印连接序列
return 0;
}