一个超难的字符串查找问题,请大家给个思路,多谢!

hamimelon 2007-11-28 09:40:35
1.实现一个检测目标字符串是否包含子串的算法,子串的规模在百万以上,也就是检查一个目标字符串中包含百万个子串中的哪一个,或者都不包含.
2.要求子串的数据结构支持增删查改.
3.要求一次检测的平均速度在0.1秒以下
...全文
202 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tiger_Zhao 2007-11-28
  • 打赏
  • 举报
回复
大学的课程都快忘光了,不过还记得子串的快速查找中关键是根据长度为n的子串s2构建一个长度为n的数组a,当在主串第i个字符与子串的第j个字符产生不匹配时,可以快速推进i=i+n[j]以提高查找速度。

所有的子串s都可以求得一个a,将所有子串按照字符的次序构建成一棵数,按照某个路径从根开始遍历的节点上的字符值就是子串,这样多个子串会经过相同的几个节点(即前面的几个字符相同),每个节点上的跳跃值取所有a[j+1]中最小的一个。

检测的方式:
①对主串s1,从i=0开始,树节点p从根节点开始。
②查看s1[i]是否能在p的子节点上找到匹配项
  如果不能:快速推进i=i+p->跳跃值,p回到跟节点,继续②
  如果能:p下降到新节点,i++
    如果p为叶子节点则找到子串,结束
    否则继续②
③如果i超出子串s1的长度则没有找到子串。
zgg___ 2007-11-28
  • 打赏
  • 举报
回复
依题意,假定要检测的字符串A长度为10^3,已经给定的字串M数目为10^6。
可以先将M排序形成字典,如果通过2分法来查字典,那么排定一个词x是否是字典内的单词,需要进行大约20次比较。那么题目相当于要判定大约10^3个单词是否在字典中,因此这种方法的计算量大约为2*10^4次比较。
要说明的问题:
1、上面说的10^3次单词判定,其实是单词的词头是否在字典中的判定,而这并不影响计算量,反而可以一定程度上优化字典。
2、字典是可维护的,可以满足增加和查改吧。如果觉得存储量还是大,就考虑hash吧。
3、这个方法假定要被检测的字符串A的长度较小,如果A的长度很大,那么这个方法就有必要改善了,但貌似不是这个问题的需求了吧。
hamimelon 2007-11-28
  • 打赏
  • 举报
回复
我现在已经把子串存在hash表中,
但是从目标子串中去对应hash表中的子串查找,时间复杂度高啊,
有没有什么办法能解决呢??
mLee79 2007-11-28
  • 打赏
  • 举报
回复
如果子串增删查改不是很多, 构造有穷自动机, 查找的时间复杂度与子串的规模无关 ...
mLee79 2007-11-28
  • 打赏
  • 举报
回复
把 flex 的代码改了改, 使他不限制状态数和规则数量, 对随机生成的2万子串生成状态表需要大约10秒钟, 在关闭输出的情况下对一个4M+的文件处理, 需要大概70毫秒, 这个速度应该可以满足楼主的要求 ...
八过 flex 貌似处理4万条规则的时候终于抗不住了, 不过即使每个状态机(按前两个字符做 hash)不超过2万条规则, 正常情况下速度 10M/秒 是可以很轻松达到的 ...

mLee79 2007-11-28
  • 打赏
  • 举报
回复
程序随机的产生1000个子串(长度3-16)的情况,如果不输出结果会更快些, 不区分大小写,
对1M以内的文件测试用时基本都小于20毫秒( PM1.4G 慢是慢了点 ), 速度应该没问题...
1M个子串在理论上速度也应该差不多, 八过偶用的 lex 貌似不支持超过 32K 的状态数, 得改改.
状态表是在程序中调用 flex 2.5.33 生成的...

代码太长, 就贴匹配的一段 :
int do1 ( unsigned char* __beg , unsigned char* end )
{
int count = 0;
int curr , st_bk , yyec , action;
unsigned char *beg = __beg , *bkup , *text;

while( beg < end )
{
curr = 1;
text = beg ;
do {
yyec = *beg ? yy_ec[*beg] : 1;
if( yy_accept[curr] ) {
st_bk = curr;
bkup = beg ;
}
while( yy_chk[ yy_base[curr] + yyec ] != curr )
{
if( (curr=yy_def[curr]) >= last_dfa )
yyec = yy_meta[ yyec ];
}
curr = yy_nxt[ yy_base[curr] + yyec ];
++beg ;
} while( yy_base[curr] != jambase );

if( !( action = yy_accept[curr] ) )
{
beg = bkup; curr = st_bk;
action = yy_accept[curr];
}

if( action != rule_def )
{

++count;
#if 1
{
unsigned char xx = *beg; *beg = 0;
printf( "find %s at pos %d\n" , text , text - __beg );
*beg = xx;
}
#endif
}
}

return count;
}


$ gcc -oxff g_substr.cpp g_table.c main.c slove.c -lstdc++ && \
time xff substr -N1000 && \
time xff gentbl && \
time xff slove * > ./result/r1
0.05user 0.04system 0:00.08elapsed 107%CPU (0avgtext+0avgdata 13520maxresident)k
0inputs+0outputs (856major+0minor)pagefaults 0swaps
call flex2.5.33(flex) return 0 , rules count 1000 , xff_tbl_i.inl
0.49user 0.32system 0:01.24elapsed 65%CPU (0avgtext+0avgdata 174976maxresident)k
0inputs+0outputs (11104major+0minor)pagefaults 0swaps
process end : Debug , file size 0 , find 0 substr , time used : 0 clock
process end : ff.h , file size 627 , find 0 substr , time used : 0 clock
process end : filter.dsp , file size 4104 , find 5 substr , time used : 0 clock
process end : filter.dsw , file size 535 , find 1 substr , time used : 0 clock
open file filter.ncb failed
process end : filter.plg , file size 1241 , find 1 substr , time used : 0 clock
process end : g_substr.cpp , file size 1500 , find 5 substr , time used : 0 clock
process end : g_table.c , file size 1628 , find 0 substr , time used : 0 clock
process end : g_table.c.bak , file size 1626 , find 0 substr , time used : 0 clock
process end : gen_tbl.c , file size 1703 , find 0 substr , time used : 0 clock
process end : main.c , file size 666 , find 0 substr , time used : 0 clock
process end : result , file size 0 , find 0 substr , time used : 0 clock
process end : slove.c , file size 3926 , find 5 substr , time used : 0 clock
process end : slove.c.bak , file size 3847 , find 4 substr , time used : 0 clock
process end : test , file size 158 , find 0 substr , time used : 0 clock
process end : test.bak , file size 160 , find 0 substr , time used : 0 clock
process end : xff.exe , file size 430912 , find 45 substr , time used : 30 clock
process end : xff.s , file size 10142 , find 1000 substr , time used : 0 clock
process end : xff.t , file size 210408 , find 0 substr , time used : 0 clock
process end : xff.temp.file.lexer.script.xx , file size 32230 , find 1000 substr , time used : 10 cl
ock
process end : xff.temp.file.lexer.script.xx.bak , file size 32076 , find 30 substr , time used : 0 c
lock
process end : xff_gen_table.exe , file size 168735 , find 1 substr , time used : 10 clock
process end : xff_tbl_i.inl , file size 256185 , find 0 substr , time used : 10 clock
Command exited with non-zero status 1
0.10user 0.03system 0:00.12elapsed 100%CPU (0avgtext+0avgdata 15568maxresident)k
0inputs+0outputs (979major+0minor)pagefaults 0swaps




33,027

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧