Boyer-Moore String搜索算法说明和正式验证

2021-04-23 10:54:19

如果以相反的顺序比较子字符串,事情可能会有所不同。例如,我们搜索A' Cat' '马龟猫'细绳。

凭借天真的算法,我们将首先比较' h'和' c'我们认为它们是不平等的字符,我们将前进的子串字符:

对,但如果我们将从&#39的结尾开始何时何地;猫'追溯到问题?我们首先比较' r'与#39; t' (&#39的最后一个字符;猫')我们看到他们不是相等的。我们可以提前一个角色前进,但是......可以'我们看到它和#39; r'中间的性格'马'部分在' cat' Substring?可以'这告诉我们一些有用的东西吗?是 - 自从' r'不是在'猫'我们可以推进' cat'细分更多,因为我们知道这将肯定会失败:

所以,如果我们看到一个人的角色而不是#39;猫'我们可以前进3个字符:

但这也会失败,也是空间('')字符缺席' cat' TOOK,我们前进3个字符:

这个很重要。 ' a' !=' t',但' a'在' cat'子字段,所以这次我们前进的只有1个字符,如在天真的搜索算法中:

所有这些都比天真的字符串搜索算法快,并且是一个强大的竞争对手,具有Knuth-Morris-Pratt算法。

这是一个硬逻辑搜索&#39的函数的源代码; cat'基下,没有其他的:

unsigned search_cat_bm_v1(char * s,unsigned len){if(len&lt 3)返回len; //找不到无符号跳过; for(无符号i = 0; i< len-2;){skip = 1; //默认跳过char char3 = s [i + 2]; //读取操作if(char3 ==' t'){char char2 = s [i + 1]; //读取操作if(char2 ==' a'){char char1 = s [i]; //读取操作if(char1 ==' c')返回i; //发现否则{// 1st字符ISN' t' c' if((char1!=' c')&(char1!=' a')&(char1!=' t')) Skip = 3; }}别的{// 2nd字符ISN' T' A' if((char2!=' c')&(char2!=' a')&(char2!=' t')) Skip = 3; }} else {//第3个字符ISN' t' t' if((char3!=' c')&(char3!=' a')&(char3!=' t')) Skip = 3;我= i +跳过;返回len; // 未找到};

** cacatsearch_cat_brute read_ops = 7search_cat_BM_v1 read_ops = 5 ** CAC catsearch_cat_brute read_ops = 10search_cat_BM_v1 read_ops = 5 ** CAC CAC catsearch_cat_brute read_ops = 17search_cat_BM_v1 read_ops = 7 **马龟catsearch_cat_brute read_ops = 16search_cat_BM_v1 read_ops = 8 **马猫turtlesearch_cat_brute read_ops = 9search_cat_BM_v1 read_ops = 5

现在下一次观察。如果我们搜索' cat'和#39; Cacat'我们看到了它和#39; C' !=' t&#39 ;,,,,,,,,,,,,,,)在' cat'子字符串,所以我们是一个角色的人。

但是......我们还可以对齐子字符串,使第一个' c' ' cat'会匹配下一个' c'在' cacat',通过推进2个字符:

我们添加规则:"如果字符串中存在错配的字符,则对齐子字符串,使它们与其匹配"或者,换句话说,"如果' c'在字符串中' t等于&#39的最后一个字符; cat'细分,提前2个字符&#34 ;:

if(char3 ==' t'){...} else {// 3rd字符ISN' t' t' if((char3!=' c')&(char3!=' a')&(char3!=' t')) Skip = 3; if(char3 ==' c')//添加skip = 2; //添加} i = i + skip;

' a' &#39中间的角色; cat'子字符串 - 我们' t打扰,因为推进一个字符的子字符串它'默认情况下相同。

这是来自R.Sedgewick'书籍的通用算法,第一个功能构建了一个'跳过',第二个是实际的搜索(Java代码):

公共博伊奥雷(String Pat){this.r = 256;这个.pat = pat; //模式在模式中最右边的位置右= new int [r]; for(int c = 0; c< r; c ++)右[c] = -1; for(int j = 0; j< pat.length(); j ++)右[pat.charat(j)] = j; } ...公共int搜索(字符串txt){int m = pat.length(); int n = txt.length(); int skip; for(int i = 0; i< = n - m; i + = skip){skip = 0; for(int j = m-1; j> = 0; j--){if(pat.charat(j)!= txt.charat(i + j)){skip = math.max(1,j - 对[txt.charat(i + j)]);休息; }}如果(skip == 0)返回i; //发现}返回n; // 未找到

如果我们搜索' cocos' Substring?如果字符在搜索模式中重复字符是什么?好吧,我们只计算最右边的角色,忽略两个第一个和#39; CO'

...展开循环搜索_cat_bm_v1.0迭代42文件bm_cat_v1.c线36函数search_cat_bm_v1线程0unwinding loop search_cat_bm_v1.0迭代43文件bm_cat_v1.c线36函数search_cat_bm_v1线程0unwinding循环搜索_cat_bm_v1.0迭代44文件bm_cat_v1.c行36功能search_cat_bm_v1线程0unwinding循环搜索_cat_bm_v1.0迭代45文件bm_cat_v1.c线36函数search_cat_bm_v1线程0unwinding循环搜索_cat_bm_v1.0迭代46文件bm_cat_v1.c线36功能search_cat_bm_v1线程0unwinding循环搜索_cat_bm_v1.0迭代47文件bm_cat_v1.c线36功能search_cat_bm_v1线程0 ......

for(无符号i = 0; i< len-2;){skip = 1; ... {if((char3!=' c')&(char3!=' a')&(char3!=' t&# 39;))Skip = 3;我= i +跳过; }

unsigned search_cat_brute(char * s,unsigned len){if(len< 3)返回len; //找不到(无符号i = 0; i< len-2; i ++){if(s [i] ==' c'&&& s [i + 1] ==&# 39; A'&& s [i + 2] ==' t')返回我; };返回len; //找不到};未签名的循环(char * s,unsigned * i_ptr){unsigned i = * i_ptr; //获得unsigned skip = 1; //默认跳过char char3 = s [i + 2]; //读取操作if(char3 ==' t'){char char2 = s [i + 1]; //读取操作if(char2 ==' a'){char char1 = s [i]; //读取操作if(char1 ==' c'){返回1; //找到} els {// 1st字符ISN' T' C' if((char1!=' c')&(char1!=' a')&(char1!=' t')) Skip = 3; }}别的{// 2nd字符ISN' T' A' if((char2!=' c')&(char2!=' a')&(char2!=' t')) Skip = 3; }} else {//第3个字符ISN' t' t' if((char3!=' c')&(char3!=' a')&(char3!=' t')) Skip = 3; if(char3 ==' c')skip = 2;我= i +跳过; * i_ptr = i; //返回返回0;};未签名搜索_cat_unrolled_v2(char * s,unsigned len){if(len&lt 3)返回len; //找不到无符号i = 0; //对于len = [3..15] if(loop_body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;如果(Loop_Body(s,& i))返回i;如果(i> =(len-2))返回len;返回len; //找不到};#ifdef cbmcvoid检查(){unsigned len = len; char s [len]; __cprover_assert(search_cat_brute(s,len)== search_cat_unrolled_v2(s,len),"断言");#结束

%time cbmc -trace - 障碍校验-dlen = 14 -dcbmc bm_cat_1_v2.ccbmc 5.10(cbmc-5.10)64位x86_64 linuxparsing bm_cat_1_v2.cconvertingtype-checking bm_cat_1_v2generation goto程序加工cprover库(x86_64)删除函数指针和虚拟函数generic属性使用8个对象位,56偏移位(默认)启动界限模型检查unwinding loop search_cat_brute.0迭代1文件bm_cat_1_v2.c行11函数search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代2文件bm_cat_1_v2.c行11函数search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代3文件bm_cat_1_v2.c行函数search_cat_brute线程0unwinding loop search_cat_brute.0迭代4文件bm_cat_1_v2.c行11函数search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代5 file bm_cat_1_v2.c行11函数search_cat_brute线程0unwinding循环搜索_cat_brute .0迭代6文件bm_cat_1_v2.c行11 fu nuple search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代7文件bm_cat_1_v2.c行11函数search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代8文件bm_cat_1_v2.c行11函数search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代9文件bm_cat_1_v2.c行11函数search_cat_brute线程0unwinding循环搜索_cat_brute.0迭代10文件bm_cat_1_v2.c行11函数search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代11文件bm_cat_1_v2.c行11函数search_cat_brute thread 0unwinding循环搜索_cat_brute.0迭代12文件bm_cat_1_v2.c行11函数search_cat_brute线程0size程序表达式:2118步骤Simple Slicing删除了2分配1.剩余的1 VCC(S),1剩余的问题在简化的问题上归因于将Sarunning命令转移的Ssarunning命令转移降低 - 处理为MiniSAT 2.2.1与简单的29262变量,75920 Clausessat检查器:实例一s Unsatefiableruntime决定程序:0.36729S **结果:[Check.Assertion.1]断言:成功** 0的1失败(1次迭代)验证成功

如果修改这些行,以便此条件表达式与其他字符相比......

CBMC仍将验证此算法并证明其正确性,因为这里的错误不会使算法不正确。它会降低其对天真字符串搜索算法的级别,as' skip = 3&#39 ;这里将被替换为' skip = 1'。它仍然可以正常工作,但慢。

它与' delta1&#39一致;来自原来的博伊尔摩尔纸的规则。但还有一个' delta2'规则,这只是另一个博客帖子的另一个故事。

请将我删除关于Bug(s)和/或建议的电子邮件:[email protected]。其他博客文章列表.BTW,我'米教学。在社交网络中关注我:Twitter,电报,Github,Discord,Facebook。