/*
1小时内完成以下算法:
Question:
有一个字符串数组,存有随机的一些英文单词,
如{‘abacus’,’deltod’,’gaff’,’giraffe’,’microphone’,’reef’,’quarlity’},
同时有另一个字母数组,如{a,e,f,f,g,i,r,q}。
请编写一个函数,用于找出在字符串数组中由字母数组中包含的字母组成的最长的字符串,
比如上述字符串数组中的正确答案为’giraffe’。
(注意:’reef’并非符合要求的候选项,因为字母数组中仅有一个’e’)
*/
//编程环境:C++ Builder 6.0
//---------------------------------------------------------------------------
#include <iostream>
#pragma hdrstop
using namespace std;
//---------------------------------------------------------------------------
const int L_W=5; //候选单词表长
const int MAXLEN=20; //候选单词最大长度
const int L_ALP = 8; //特征字母表中字母个数
char words[L_W][MAXLEN] = //候选单词表
{
"aef",//"abacus",
"fgir",//"deltod",
"gaff",
"giraffe",
"microphone"
};
char c_alpha[L_ALP]={'a', 'e', 'f', 'f', 'g', 'i', 'r', 'q' }; //特征字母表
//---------------------------------------------------------------------------
char * SortChars(char words[], int len);//字符串按字母大小升序排列:冒泡排序
int StrComp(char str1[], int len1, char str2[], int len2);//字符串模式匹配,返回值:成功1,失败0
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
int len_wds[L_W]; //单词长度表
char vrf_1[L_W]; //首次验证长度
char sort_words[L_W][MAXLEN];//按字母升序排列的新单词表
//一、求每个单词的长度
for (int i=0; i<L_W; i++)
{
len_wds[i] = strlen(words[i]);
}
//二、首先排除长度大于字母表的单词
for (int j=0; j<L_W; j++)
{
if ( len_wds[j] > L_ALP )
vrf_1[j]='N';
else
vrf_1[j]='Y';
}
//三、对每一个vrf_1[j]=='Y'的单词,对其组成部分(字母)进行升序排序
//同时,对排序后的单词依次与字母表进行模式匹配(字母表为主串)
int vrf_2[L_W]={0}; //模式匹配成功标志1,初始化0
for (int k=0; k<L_W; k++)
{
if ('Y'==vrf_1[k])
{
strcpy(sort_words[k], words[k]);
//子函数, 形成新单词
SortChars(sort_words[k], len_wds[k]) ;
// 子函数, 模式匹配
vrf_2[k] = StrComp( c_alpha, L_ALP, sort_words[k], len_wds[k] );
}
else
{
strcpy(sort_words[k],"");
}
}
//四、寻找目标单词
int flg = -1; //记录目标单词在单词表中的下标,默认为未找到
int len_tmp = 0;//目标单词长度
for (int m=0; m<L_W; m++)
{
if ( 1 == vrf_2[m] )
{
if ( len_tmp <= len_wds[m] )
{
flg = m;
len_tmp = len_wds[m];
}
}
}
//将sort_words中的每一个单词与c_alpha进行模式匹配
//若匹配成功则记录其下标:vrf_2[]={0,0,0,1,0}为模式匹配结果
//对于vrf_2[i]为1的,根据len_wds[]确定长度最大的有效单词
//若不止一个单词vrf_2[]为1的,则设置一个标志位,循环(i:1~L_W)比较
//直到找到 len_wds[i] 最大的,返回i
//打印c_alpha[i-1]
//本例中只有vrf_2[3]为1,则打印c_alpha[3] "giraffe"
if ( 0==len_tmp || -1==flg )
cout<<"未找到目标单词"<<endl;
else
cout<<"目标单词为:"<<words[flg]<<endl;
//vrf_2[1] = StrComp( c_alpha, L_ALP, sort_words[1], len_wds[1] ); //测试
return 0;
}
//---------------------------------------------------------------------------
//选择排序子函数:用于给每个单词排序,生成新的单词表sort_words[L_W][MAXLEN]
//冒泡法:参考本人【博文】http://blog.csdn.net/luxer_1985/article/details/8178673
char* SortChars(char words[], int len)
{
int i, j, t;
for (i=len-1; i>0; i--)//每轮比较words[0]~words[i],每轮比较结束words[i]是该轮中最大数
{
for (j=0; j<i; j++)//每一轮中比较相邻两数大小
{
if ( *(words+j) > *(words+j+1) ) //前大后小,则两两交换
{
t = *(words+j);
*(words+j) = *(words+j+1);
*(words+j+1) = t;
}
}
}
return words;
}
//---------------------------------------------------------------------------
//模式匹配子函数:用户将每个单词作为子串,与主串c_alpha进行匹配,据此设置vrf_2[]={0,0,0,1,0}
//参数说明:str1主串,str2子串,len1主串长度,len2子串长度
//模式匹配研究:参考本人【博文】http://blog.csdn.net/luxer_1985/article/details/7266136
int StrComp(char str1[], int len1, char str2[], int len2)
{
for (int i=0; i< len1-len2+1; i++) //计算匹配信息
{
int k=0;//一次匹配过程中,子串在主串内匹配成功的字符数
for (int j=0; j<len2; j++)
{
if ( str1[i+j] == str2[j] )
{
k++;
}
if (k==len2) //匹配成功
return 1;
}
}
return 0;
}
//---------------------------------------------------------------------------
一、算法的综合时间复杂度为O(N.^3):子函数(排序算法、字符串模式匹配)时间复杂度均为OO(N.^2),主函数的一维循环中调用了子函数;
二、算法优化途径:
1. 对每个单词按所含字母进行排序的优化算法可用快速排序等算法进行优化;
2. 对字符串模式匹配可用KMP算法进行优化。
3. 考虑设计其他数据结构用于存储单词表、特征字母表等,以便提高程序执行效率。