Intel的朋友,能否推荐一个高效率的ANSI不区分大小写的检索函数?

danscort2000 2007-03-29 01:19:51
想在一个ANSI 字符串中检索一个子字符串
不区分大小写,也就是大写和小写看作一个字符
目前使用的方法是先拷贝,然后全部转换到小写,再调用strstr来进行检索
感觉效率太低,
有没有高手能提供一个高效率的函数?或者思路也行
不要使用CString string等,全部采用 char 指针进行操作,非常感谢
...全文
385 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
flyingdog 2007-04-05
  • 打赏
  • 举报
回复
既然你用上了汇编,那就有其他办法提高速度了。
比如字符比较没必要一个一个比。每个字符是8位的,对于搜索字符是4个字符的情况。正好32位。可以进行32位的同时比较。
至于搜索字符不是正好4个字符的情况,也可以想办法。
flyingdog 2007-04-05
  • 打赏
  • 举报
回复
在程序运行时进行大小写转换虽然剩了复制的时间。但是怎么多条件判断会影响cpu的执行性能的。
还是试试使用查表转换的方法。
flyingdog 2007-04-05
  • 打赏
  • 举报
回复
后缀树和后缀数组就算了,实现复杂,常数大。
针对这个数据规模,其他算法可能没什么用。但是KMP的常数应该不大。
贴一个KMP模板。只是模板,不针对这个程序。
#define MAXLEN 1000

int T[MAXLEN];

void kmp_table(char *P){
int i=0;
int j=-1;
char c='\0';

T[0]=j;
while (P[i]!='\0'){
if (P[i]==c){
T[i+1]=j+1;
++j;
++i;
}
else if (j>0){
j=T[j];
}
else {
T[i+1]=0;
++i;
j=0;
}
c = P[j];
}
}

int kmp_search(char *P, char *S){
kmp_table(P);
int m = 0;
int i = 0;

while (S[m+i]!='\0'&&P[i]!='\0') {
if (S[m+i]==P[i]){
++i;
}
else {
m+=i-T[i];
if (i>0)i=T[i];
}
}

if (P[i]=='\0'){
return m;
}
else {
return m+i;
}
}
flyingdog 2007-04-05
  • 打赏
  • 举报
回复
为什么一定要偶数?
比如3个字符的时候,把最高位与成0不是就行了?
flyingdog 2007-04-05
  • 打赏
  • 举报
回复
你前面不是说“而检索子串一般是2到8个字符”??
怎么现在又变成“可能超过16个字符”??
那就先做一个判断,对于短的使用汇编优化掉,对于长的使用KMP。
danscort2000 2007-04-05
  • 打赏
  • 举报
回复
对于是4个字符或者8个字符,这个确实可以优化
问题是这个长度是用户指定的,可能超过16个字符,不一定是偶数
如果要针对性优化,恐怕前面的判断部分和后续的分支判断就需要大量的CPU时间了
所以暂时不用
今天修改了函数,对IO又进行了优化,首先判断长度,用FOR代替了WHILE,这样里面的判断又少了很多
danscort2000 2007-04-05
  • 打赏
  • 举报
回复
现在已经找到方法了,不用ASM汇编,也不用KMP,
目前的逻辑是:
首先计算两个长度
然后对子串全部大写或者小写
用两个FOR代替WHILE[这里可以根据子串的长度优化掉一部分检索]
这样的函数速度比原来汇编的那个还快
danscort2000 2007-04-05
  • 打赏
  • 举报
回复
你前面不是说“而检索子串一般是2到8个字符”??
怎么现在又变成“可能超过16个字符”??
那就先做一个判断,对于短的使用汇编优化掉,对于长的使用KMP。

这个已经说明是一般了,因为这是用户决定的检索关键字
并没有规定最长长度,根据统计资料,一般就是2-8个字符
danscort2000 2007-04-04
  • 打赏
  • 举报
回复
KMP检索函数有了
但是我看了实现
太慢了,这个对全文检索可能意义不错,但是用在我这个场合比我的还慢,
现在用这个实现,如何?
char *AsmStrStrI(char *p1, char *p2) // p1=source
{
char c=0;
while(*p1)
{
__asm
{
mov ecx, p1
mov edx, p2
StartLoop:
mov al, [ecx]
mov ah, [edx]
inc ecx
inc edx

cmp al,0
je EndLoop
cmp ah,0
je EndLoop

cmp al, 'a'
jb Next
cmp al, 'z'
ja Next
and al, 11011111b
Next:
cmp ah, 'a'
jb Compare
cmp ah, 'z'
ja Compare
and ah, 11011111b
Compare:
cmp al, ah
je StartLoop
EndLoop:
mov c, ah
}
if(c==0)
{
return p1;
}
p1++;
}
return NULL;
}
赖勇浩 2007-04-04
  • 打赏
  • 举报
回复
这个肯定是慢了,楼主先实现一个KMP算法吧~

还有一些比KMP更快的算法,你可以找一下相关的ACM论文。
danscort2000 2007-04-04
  • 打赏
  • 举报
回复
现在的优化是,
我在调用前,首先对子串UPCASE
然后传入这个函数
因此没有最前面的那个while循环
danscort2000 2007-04-04
  • 打赏
  • 举报
回复
上面有个错误,加了const ,应该是 char *
danscort2000 2007-04-04
  • 打赏
  • 举报
回复
char * AnsiNocaseStrstr(const char *src,const char *sub)
{
if(*sub==0) return NULL;
if (*src == 0)
{
if (*sub) return NULL;
return src;
}

char c;
size_t i=0;
while(sub[i])
{
if(sub[i] >= 'A' && sub[i] <= 'Z') sub[i] += 0x20;
i++;
}

while (*src)
{
i=0;
while (1)
{
if(sub[i] == 0) return src;
if(src[i]==0) return NULL;
c=src[i];
if(c >= 'A' && c <= 'Z') c += 0x20;
if( sub[i] != c) break;
i++;
}
src++;
}
return NULL;
}
IntelSupport 2007-04-04
  • 打赏
  • 举报
回复
能不能举个一般性能的ANSI不区分大小写的检索函数先
danscort2000 2007-04-03
  • 打赏
  • 举报
回复
哎,看来是没有办法了
等等看,有没有更好的方法
flyingdog 2007-04-01
  • 打赏
  • 举报
回复
的确有PCMPEQB指令,可以进行8个或者16个的同时比较,但是这个并不适合你的要求。因为比较结果是写入mask位,而不是更改flag值。而且无法解决大小写转换问题。具体的指令用法你可以查相应文档。
danscort2000 2007-03-31
  • 打赏
  • 举报
回复
现在是自己写代码了,去掉了内存拷贝转换导致的时间,
大小写直接比较,
由于子串一般都很小,比如2个字符到4个字符,很复杂的算法我不知道是否反而导致低效率
明天继续进行优化,
我想知道是否可以利用MMX啊?
flyingdog 2007-03-31
  • 打赏
  • 举报
回复
如果真要非常注重高效,还是自己写代码比较好。

你使用KMP算法试试,复杂度是O(n+m)。

至于大小写问题,我想到一个方法,不需要先拷贝再转小写,但是不知道实际效果如何,你可以试试。也欢迎大家讨论。
比如对于A和a来说,搜索子串先转成小写。定义一个长度为256的数组T[256]
T['a']='a'
T['A']='a'
T[str[i]]就能在比较时进行转换。

danscort2000 2007-03-30
  • 打赏
  • 举报
回复
只要找到一个就可以了
不需要全部
danscort2000 2007-03-30
  • 打赏
  • 举报
回复
谢谢,不过不想用四string类
因为我有上万个字符串,每个串一般是16个到128个字符
而检索子串一般是2到8个字符
我希望是ANSI检索函数,事实上那个strstr是我自己重新写过的
主要想避免内存分配与拷贝,这个过程太耗费时间,
想将大小写检索都放在一个函数中
其实INTEL 可以开发一个高效率而简短的ANSI检索函数,这个经常要用到的
加载更多回复(2)

568

社区成员

发帖
与我相关
我的任务
社区描述
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
社区管理员
  • 英特尔技术社区
  • shere_lin
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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