现在的位置: 首页 > 综合 > 正文

一个字符串的面试题

2012年11月01日 ⁄ 综合 ⁄ 共 2490字 ⁄ 字号 评论关闭

题目:

 

        有一字符串由M个单词组成单词之间有空格隔开(只有空格,没有其他标点符号),有N个关键字,现在要在字符串中找出包含N个关键字(每个关键字至少出现一次,没有说要不要按什么顺序)的最短子串。函数原型:String extractSummary(String description, String[] keywords)

 

 

思路:

 

 

想了一阵,想出了一个方法,设主串长n 关键字长m 则复杂度大致为nlogm

举个例子说下过程:

例如主串: ab ba ad ba ab ef ba ab ef ad

关键字集合 ab ef ad

则查找过程如下:

起始扫描到ab,ab出现次数加一,start赋值0,此时出现了一个关键字

扫描到ba,发现不是关键字,则跳过

扫描到ad,将ad出现次数加一,将上一次扫描到的关键字ab的next[0]赋值2,此时一共出现了2个关键字

扫描到ba,不是关键字跳过

扫描到ab,将ab出现次数加一,发现start所指的关键字出现了两次,因此start所指关键字是多余的,将start指向的关键字ab出现次数减一,并令start=next[start],重复这个过程直至start所指关键字

只出现一次,

扫描到ef,将next[4]赋值5,此时start=2,将ef出现次数加一,此时发现3个关键字均已出现,判断是否为当前最优解....

扫描ba,不是关键字跳过

扫描ab,将上次出现关键字ef的下一个关键字next[5]赋值7,将ab出现次数加一

扫描ef,将上次出现关键字ab的下一个关键字next[7]赋值8,将ef出现次数加一

扫描ad,将上次出现关键字ef的下一个关键字next[8]赋值9,将ad出现次数加一,发现start所指关键字出现多次,因此将start所指关键字出现次数减一, 利用next数组不断跳转,直至start所指关键字只出现一次为止

根据上面过程,可以得到最优解起始8 长度3

 

 

程序如下,没按照给的函数名,直接写在主函数了:

输入:
10
ab ba ad ba ab ef ba ab ef ad
3
ab ef ad

输出
8 3

 

 

 

证明下上面算法的正确性:

设包含所有关键字的最短区间起始位置start, 终止位置i, 则可以推出如下性质:

1. start所指向的单词一定是关键字.(否则必然能缩短区间长度)

2. start所指向的关键字必然在这个最短区间内只出现一次,(否则区间长度至少还能缩小1)

证明:

当区间末尾扫描到i时,由于[start , i]包含了所有关键字,由于start所指向的关键字只在该区间内出现

一次,因此由"while(everkeynum[j]>1)"循环可知必然会在start处停止,此时会更新以前保存的最短长度,故该方法能找到解.

嫌麻烦直接开了个next数组,呵呵,有点浪费空间,可以用链表实现next数组节省空间....

 

抱歉!评论已关闭.