关于串匹配问题之莫名的超超高效率匹配

z54604 2009-01-31 12:21:10
加精
这是我的strstr实现:
char *qsearch(const char *str, int slen, const char *patt, int plen)
{
const char *s, *p, *tx = str;
static int td[128],c=0;
/*************预处理*****************************/
for ( ++plen; c < 128; ++c) //建立表
td[c] = plen ;
--plen; //复原

for (p=patt; *p; p++) //初始化表
td[*p] = plen - (p - patt);//m-(p-patt)即失配时模式串右移的步数

/***************模式匹配开始*********************/
while ( (s=tx+plen-1) <= str+slen-1) {
for (p = patt+plen-1; *p == *s; --s)
--p;
if (*p == 0) // 找到并返回
return (char*)tx;
tx += td[tx[plen]]; // 模式右移
}
return NULL;
}

一:这个是网上找到strstr实现1
char * strstr (buf, sub)
register char *buf;
register char *sub;
{
register char *bp;
register char *sp;

if (!*sub)
return buf;
while (*buf)
{
bp = buf;
sp = sub;
do {
if (!*sp)
return buf;
} while (*bp++ == *sp++);
buf += 1;
}
return 0;
}

二:这是gcc的实现
const char * bstrstr(const char *src, const char *needle)
{
const char *p1, *p2;

p1 = src;
p2 = needle;
while (*src != '\0' && *needle != '\0')
{
if (*src++ != *needle++) {
needle = p2;
src = ++p1; //从下一个字符开始搜索needle
}
}
if (*needle == '\0')
return p1;

return NULL;
}

测试字符串char *s="sjuwfdjkasbUYTGdflksjflkhjdslkdlkfhjBWEVFBSDJKJBHSDsaFdfasIUasGW
EFkasfhskaddsajiudvdbkajdsfgviausdgEJSAHDKJAKJGHhsadhbjjh";
char *t="sad";
进行一千万次

有个很奇怪的现象,我的实现(sunday) 的时间是 3062ms,kmp算法实现是 9112ms,一的实现是1133ms
可是gcc那个实现竟然是36ms!!!
gcc那个实现和一的实现可以说没区别,都是朴素匹配,为什么那个时间那么快!!!?????????
...全文
1679 62 打赏 收藏 转发到动态 举报
写回复
用AI写文章
62 条回复
切换为时间正序
请发表友善的回复…
发表回复
wyf5060060 2011-03-08
  • 打赏
  • 举报
回复
太深奥了 学习下。。。
华亭真人 2011-03-08
  • 打赏
  • 举报
回复
LS都是神仙
linguranus 2011-03-08
  • 打赏
  • 举报
回复
有点夸大,应该有几倍的提高比原来的汇编代码。
[Quote=引用 58 楼 linguranus 的回复:]
用这个吧,会对你的代码比原有的汇编快多个数量级。
http://permalink.gmane.org/gmane.comp.lib.glibc.alpha/14513
[/Quote]
linguranus 2011-03-08
  • 打赏
  • 举报
回复
用这个吧,会对你的代码比原有的汇编快多个数量级。
http://permalink.gmane.org/gmane.comp.lib.glibc.alpha/14513
boyisjl 2010-10-19
  • 打赏
  • 举报
回复
good,收藏~
shunzi__1984 2009-02-12
  • 打赏
  • 举报
回复
收藏
  • 打赏
  • 举报
回复
这种所谓的“优化”并没有多少实际的意义,真正的软件中谁会把对同一个串进行N次同样的子串查找?

在我的实际测试中,使用DEV-CPP 4.9.9.2,把你的qsearch加上__MINGW_ATTRIB_PURE属性:
__MINGW_ATTRIB_PURE char *qsearch(const char *str, int slen, const char *patt, int plen)
{
//...
}
同样获得了15ms的结果。

至于你为什么“并没有优化到”,也许是你的编译选项设置的问题。
z54604 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 DelphiGuy 的回复:]
to 楼主:
这就是循环优化的结果,你就不要再瞎猜了。
根本就没有什么“莫名的超超高效率”strstr,写得很烂的strstr和最高效的strstr相比也到不了数量级的差距(别拿脚本语言的实现和真编译代码的实现相比啊)。

你想想执行一千万次才用35ms(在我的机器上是15~16ms,偶尔是0),平均一次才3.5ns。
3.5ns能执行几条指令?撑死了一二十条(都是极快的指令、多个处理单元没有空闲、每个处理单元的流水线都没有任何停顿…
[/Quote]


那么究竟怎样才能优化?加了那些关键字可是并没有优化到,要有什么条件?
niukuo 2009-02-05
  • 打赏
  • 举报
回复
问一下如果遇到字符'\0'怎么办?
比如:“abc\0123456789” “123”
无天 2009-02-04
  • 打赏
  • 举报
回复
MARK
yutaooo 2009-02-04
  • 打赏
  • 举报
回复
占位
  • 打赏
  • 举报
回复
45楼那个代码就一个字形容:慢。:)
minisnake9 2009-02-04
  • 打赏
  • 举报
回复
仔细检查一下
xyfl1818 2009-02-03
  • 打赏
  • 举报
回复
FastReport 4.33 Enterprise 怎么安装忘了,谁来提示一下
zcz128 2009-02-03
  • 打赏
  • 举报
回复
学习
z54604 2009-02-03
  • 打赏
  • 举报
回复
string.h 那个strstr汇编代码谁把它贴上来一下啦
momomowere 2009-02-03
  • 打赏
  • 举报
回复
ding
canhuiqin 2009-02-03
  • 打赏
  • 举报
回复
好,不错!!!!!
z54604 2009-02-03
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 DelphiGuy 的回复:]
to 14楼:

你肯定没有做rebuild all。
为了避免用strstr带来的混淆,这么说吧,你把你的qsearch声明成:
__MINGW_ATTRIB_PURE char *qsearch(const char *str, int slen, const char *patt, int plen)
它也会变成“莫名的超超高效率”。

[/Quote]

rebuild all 了,用了__MINGW_ATTRIB_PURE真的也没快到...

开 -o3优化,qsearch的汇编代码
_qsearch:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl 8(%ebp), %eax
movl %eax, -12(%ebp)
leal 20(%ebp), %eax
incl (%eax)
L6:
cmpl $127, c.1
jg L7
movl c.1, %edx
movl 20(%ebp), %eax
movl %eax, td.0(,%edx,4)
incl c.1
jmp L6
L7:
leal 20(%ebp), %eax
decl (%eax)
movl 16(%ebp), %eax
movl %eax, -8(%ebp)
L9:
movl -8(%ebp), %eax
cmpb $0, (%eax)
je L12
movl -8(%ebp), %eax
movsbl (%eax),%ecx
movl 16(%ebp), %edx
movl -8(%ebp), %eax
subl %edx, %eax
movl %eax, %edx
movl 20(%ebp), %eax
subl %edx, %eax
movl %eax, td.0(,%ecx,4)
leal -8(%ebp), %eax
incl (%eax)
jmp L9
L12:
movl 20(%ebp), %eax
addl -12(%ebp), %eax
decl %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %edx
movl 12(%ebp), %eax
addl 8(%ebp), %eax
decl %eax
cmpl %eax, %edx
ja L13
movl 20(%ebp), %eax
addl 16(%ebp), %eax
decl %eax
movl %eax, -8(%ebp)
L14:
movl -8(%ebp), %eax
movl -4(%ebp), %edx
movzbl (%eax), %eax
cmpb (%edx), %al
jne L15
leal -8(%ebp), %eax
decl (%eax)
leal -4(%ebp), %eax
decl (%eax)
jmp L14
L15:
movl -8(%ebp), %eax
cmpb $0, (%eax)
jne L17
movl -12(%ebp), %eax
movl %eax, -16(%ebp)
jmp L5
L17:
movl -12(%ebp), %eax
addl 20(%ebp), %eax
movsbl (%eax),%eax
movl td.0(,%eax,4), %edx
leal -12(%ebp), %eax
addl %edx, (%eax)
jmp L12
L13:
movl $0, -16(%ebp)
L5:
movl -16(%ebp), %eax
leave


const char * bstrstr(const char *src, const char *needle)
{
const char *p1, *p2;

p1 = src;
p2 = needle;
while (*src != '\0' && *needle != '\0')
{
if (*src++ != *needle++) {
needle = p2;
src = ++p1; //从下一个字符开始搜索needle
}
}
if (*needle == '\0')
return p1;

return NULL;
}的汇编代码
_bstrstr:
pushl %ebp
movl %esp, %ebp
subl $12, %esp
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
movl 12(%ebp), %eax
movl %eax, -8(%ebp)
L19:
movl -4(%ebp), %eax
cmpb $0, (%eax)
je L20
movl -8(%ebp), %eax
cmpb $0, (%eax)
je L20
movl -4(%ebp), %eax
movl %eax, %edx
movl -8(%ebp), %eax
movl %eax, %ecx
leal -8(%ebp), %eax
incl (%eax)
leal -4(%ebp), %eax
incl (%eax)
movzbl (%edx), %eax
cmpb (%ecx), %al
je L19
movl 12(%ebp), %eax
movl %eax, -8(%ebp)
incl 8(%ebp)
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
jmp L19
L20:
movl -8(%ebp), %eax
cmpb $0, (%eax)
jne L22
movl -4(%ebp), %eax
movl %eax, -12(%ebp)
jmp L18
L22:
movl $0, -12(%ebp)
L18:
movl -12(%ebp), %eax
leave

char* astrstr(const char *buf, const char *sub)
{
register char *bp;
register char *sp;

if (!*sub)
return (char *)buf;
while (*buf)
{
bp = (char *)buf;
sp = (char *)sub;
do {
if (!*sp)
return (char *)buf;
} while (*bp++ == *sp++);
buf += 1;
}
return 0;
}
的汇编代码
_astrstr:
pushl %ebp
movl %esp, %ebp
subl $12, %esp
movl 12(%ebp), %eax
cmpb $0, (%eax)
jne L25
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
jmp L23
L25:
movl 8(%ebp), %eax
cmpb $0, (%eax)
je L26
movl 8(%ebp), %eax
movl %eax, -8(%ebp)
movl 12(%ebp), %ecx
movl %ecx, -12(%ebp)
L27:
movl -12(%ebp), %eax
cmpb $0, (%eax)
jne L29
movl 8(%ebp), %eax
movl %eax, -4(%ebp)
jmp L23
L29:
movl -12(%ebp), %ecx
movzbl (%ecx), %edx
incl -12(%ebp)
movl -8(%ebp), %ecx
movzbl (%ecx), %eax
incl -8(%ebp)
cmpb %dl, %al
jne L28
jmp L27
L28:
incl 8(%ebp)
jmp L25
L26:
movl $0, -4(%ebp)
L23:
movl -4(%ebp), %eax
leave
nettman 2009-02-03
  • 打赏
  • 举报
回复
学习!
加载更多回复(41)

33,007

社区成员

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

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