免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2373 | 回复: 3
打印 上一主题 下一主题

字符串近似匹配算法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-20 11:28 |只看该作者 |倒序浏览
字符串的近似匹配,就是允许在匹配时有一定的误差,比如在字串“以前高手好久不见”中找“以前是高手”也能成功。具体地说,错误可以有三种类型:加字符(以前也是高手)、漏字符(以前高手)和替换字符(以前石膏手)。下面的函数在text中查找子串pat,最多允许有k个错误。返回的是匹配的终点(我还没想好如何确定起点,呵呵)。
至于算法的原理,现在一下子说不清楚,只能说这是一个非确定性有限自动机,以后有时间的话再详细介绍。有兴趣的话可以自己去看文章《Faster Approximate String Matching》, Algorithmica (1999) 23: 127-158。

算法的限制:(m-k)*(k+2) <= 64, 这里m是子串的长度。那个64是因为哦用了64位整数来编码自动机的状态。如果允许两个错误,则子串最长为18个字符,对一般应用来说足够了。
  1. char* amatch(const char* text, const char* pat, int k)
  2. {
  3.   int m = strlen(pat);
  4.   assert(m-k&gt;0);
  5.   assert((m-k)*(k+2)<= 64);
  6.   int j;
  7.   __int64 Din = 0;
  8.   __int64 M1 = 0;
  9.   __int64 M2 = 0;
  10.   __int64 M3 = 0;
  11.   __int64 G = 1 << k;
  12.   int onekp1 = (1 << (k+1)) - 1;
  13.   for (j=0; j<m-k; j++)
  14.   {
  15.     Din = (Din << (k+2))|onekp1;
  16.     M1 = (M1 << (k+2))|1;
  17.     if (j < m-k-1)
  18.       M2 = (M2 << (k+2)) | 1;
  19.   }
  20.   M2=(M2<<(k+2))|onekp1;
  21.   __int64 D=Din;
  22.   const char* s=text;
  23.   int c=*s++;
  24.   while(c)
  25.   {
  26.     int found=0;
  27.     const char* sp=pat;
  28.     for(j=0;j<k+1;j++)
  29.     {
  30.       int cp=*sp++;
  31.       if(c==cp)
  32.       {
  33.         found=1;
  34.         break;
  35.       }
  36.     }
  37.     if(found)
  38.     {
  39.       do
  40.       {
  41.         __int64 tc = 0;
  42.         const char* sp = pat;
  43.         for (j=0; j<m; j++)
  44.         {
  45.           int cp = *sp++;
  46.           if (c!=cp)
  47.           c|=(1<<j);
  48.         }
  49.         __int64 Tc = 0;
  50.         for (j=0; j<m-k; j++)
  51.         Tc = (Tc<<(k+2))|((tc&gt;>j)&onekp1);
  52.         __int64 x = (D&gt;>(k+2))|Tc;
  53.         D=((D<<1)|M1)&((D<<(k+3))|M2)&(((x+M1)^x)&gt;>1)&Din;
  54.         if((D & G) == 0)
  55.           return (char*)s;
  56.         if(D != Din)
  57.           c = *s++;
  58.       }
  59.       while ( D != Din && c);
  60.    }
  61.    if (c)
  62.      c = *s++;
  63. }
  64. return NULL;
  65. }  
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-12-28 23:15 |只看该作者
谢谢分享

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:50:28
3 [报告]
发表于 2011-12-29 09:08 |只看该作者
看看这个吧:http://blog.youxu.info/spell-correct.html
goolge的工程师,在飞机上写的20多行的python代码。
原文的后面,有C语言的版本。

论坛徽章:
24
狮子座
日期:2013-12-31 10:48:0015-16赛季CBA联赛之吉林
日期:2016-04-18 14:43:1015-16赛季CBA联赛之北控
日期:2016-05-18 15:01:4415-16赛季CBA联赛之上海
日期:2016-06-22 18:00:1315-16赛季CBA联赛之八一
日期:2016-06-25 11:02:2215-16赛季CBA联赛之佛山
日期:2016-08-17 22:48:2615-16赛季CBA联赛之福建
日期:2016-12-27 22:39:272016科比退役纪念章
日期:2017-02-08 23:49:4315-16赛季CBA联赛之八一
日期:2017-02-16 01:05:3415-16赛季CBA联赛之山东
日期:2017-02-22 15:34:5615-16赛季CBA联赛之上海
日期:2017-11-25 16:17:5015-16赛季CBA联赛之四川
日期:2016-01-17 18:38:37
4 [报告]
发表于 2011-12-29 11:49 |只看该作者
keehoo 发表于 2011-12-20 11:28
字符串的近似匹配,就是允许在匹配时有一定的误差,比如在字串“以前高手好久不见”中找“以前是高手”也能 ...



     这个不错。{:3_189:}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP