(笔试前准备)字符串匹配算法总结

2023-11-18

我想说一句“我日,我讨厌KMP!”。
KMP虽然经典,但是理解起来极其复杂,好不容易理解好了,便起码来巨麻烦!
老子就是今天图书馆在写了几个小时才勉强写了一个有bug的、效率不高的KMP,特别是计算next数组的部分。

其实,比KMP算法速度快的算法大把大把,而且理解起来更简单,为何非要抓住KMP呢?笔试出现字符串模式匹配时直接上sunday算法,既简单又高效,何乐而不为?
说实话,想到sunday算法的那个人,绝对是发散思维,绝对牛。当我在被KMP折磨的够呛的时候,我就琢磨,有没有别的好算法呢??琢磨了半天也没想出个所以然来。笨啊,脑子不够发散。

下面贴上一位兄弟写的算法总结,很简单(建议KMP部分就不用看了,看了费脑子)。
参见:http://hi.baidu.com/willamette/blog/item/02bd0b5599c8b4c0b645ae06.html

趁着做Presentation的功夫,顺便做一个总结

字符串匹配:

---willamette

在匹配串中寻找模式串是否出现,注意和最长公共子序列相区别(LCS: Longest Common Substring)


-: Brute Force(BF或蛮力搜索) 算法:

这是世界上最简单的算法了。
首先将匹配串和模式串左对齐,然后从左向右一个一个进行比较,如果不成功则模式串向右移动一个单位。

速度最慢。

那么,怎么改进呢?

我们注意到Brute Force 算法是每次移动一个单位,一个一个单位移动显然太慢,是不是可以找到一些办法,让每次能够让模式串多移动一些位置呢?

当然是可以的。

我们也注意到,Brute Force 是很不intelligent 的,每次匹配不成功的时候,前面匹配成功的信息都被当作废物丢弃了,当然,就如现在的变废为宝一样,我们也同样可以将前面匹配成功的信息利用起来,极大地减少计算机的处理时间,节省成本。^_^

注意,蛮力搜索算法虽然速度慢,但其很通用,文章最后会有一些更多的关于蛮力搜索的信息。


-: KMP算法

首先介绍的就是KMP 算法。

原始论文:Knuth D.E., Morris J.H., and Pratt V.R., Fast pattern matching in strings, SIAM Journal on Computing, 6(2), 323-350, 1977.

这个算法实在是太有名了,大学上的算法课程除了最笨的Brute Force 算法,然后就介绍了KMP 算法。也难怪,呵呵。谁让Knuth D.E. 这么world famous 呢,不仅拿了图灵奖,而且还写出了计算机界的Bible <The Art of Computer Programming>( 业内人士一般简称TAOCP). 稍稍提一下,有个叫H.A.Simon 的家伙,不仅拿了Turing Award ,顺手拿了个Nobel Economics Award ,做了AI 的爸爸,还是Chicago Univ 的Politics PhD ,可谓全才。

KMP 的思想是这样的:

利用不匹配字符的前面那一段字符的最长前后缀来尽可能地跳过最大的距离

比如

模式串ababac 这个时候我们发现在c 处不匹配,然后我们看c 前面那串字符串的最大相等前后缀,然后再来移动

下面的两个都是模式串,没有写出来匹配串

原始位置 ababa c

移动之后 aba bac

因为后缀是已经匹配了的,而前缀和后缀是相等的,所以直接把前缀移动到原来后缀处,再从原来的c 处,也就是现在的第二个b 处进行比较。 这就是KMP 。


-:Horspool算法

Horspool 算法。

当然,有市场就有竞争,字符串匹配这么大一个市场,不可能让BF 和KMP 全部占了,于是又出现了几个强劲的对手。

第一个登场的是

论文:Horspool R.N., 1980, Practical fast searching in strings, Software - Practice & Experience, 10(6):501-506

Horspool 算法的思想很简单的。不过有个创新之处就是模式串是从右向左进行比较的。很好很强大,为后来的算法影响很大。

匹配串:abcbc sdxzcxx

模式串:cbcac

这个时候我们从右向左进行对暗号,c-c ,恩对上了,第二个b-a ,不对啊,我们应该怎么办?难道就这么放弃么。于是,模式串从不匹配的那个字符开始从右向左寻找匹配串中不匹配的字符b 的位置,结果发现居然有,赶快对上赶快对上,别耽误了。

匹配串:abcbcsd xzcxx

模式串: cbcac

然后继续从最右边的字符从右向左进行比较。这时候,我们发现了,d-c 不匹配啊,而且模式穿里面没有噢,没办法,只好移动一个模式串长度的单位了。

匹配串:abcbcsdxzcxx

模式串:      cbcac

-:Boyer-Moore算法

第二个上来的是Boyer-Moore 算法。

是一个很复杂的算法,当然,虽然理论上时间复杂度和KMP 差不多,但是实际上却比KMP 快数倍,可见实践是检验真理的唯一标准。

原始论文:R.S.Boyer, J.S.Moore, A fast string searching algorithm , Communications of the ACM,20(10):762-772 ,1977

分为两步预处理,第一个是bad-character heuristics ,也就是当出现错误匹配的时候,移位,基本上就是做的Horspool 那一套。

第二个就是good-suffix heuristics ,当出现错误匹配的时候,我还要从不匹配点向左看啊,以前匹配的那段子字符串是不是在模式串本身中还有重复的啊,有重复的话,那么我就直接把重复的那段和匹配串中已经匹配的那一段对齐就是了。再比较

匹配串:abaccba bbazz

模式串:cbadcba

我们看到已经匹配好了cba ,但是c-d 不匹配,这个时候我们发现既可以采用bad-character heuristics ,也可以使用good-suffix heuristics( 模式串:cba dcba ) ,在这种情况下,邪不压正。毅然投奔good 。移动得到

匹配串:abaccbabbaz z

模式串:    cbadcba

可是,我们有时候也发现,已经匹配好的那一部分其实并没有再有重复了的啊。这个时候,我们发现已经匹配好的那串字符串有一部分在开头重新出现了,那么,赶快,对齐吧。

匹配串:abacccb bbazz

模式串:cbadccb

然后得到

匹配串:abacccbbbazz

模式串:     cbadccb

当两种Good-Suffix 出现的时候,取移动距离最大的那个。

对于BM算法,好规则和坏规则,这里讲的不够明确,下面推荐一个讲解非常优秀的文章,可谓图文并茂啊,而且还是个MM写的。
Boyer-Moore 经典单模式匹配算法
http://blog.csdn.net/iJuliet/archive/2009/05/19/4200771.aspx


-:Sunday算法

最后一个是Sunday 算法,实际上比Boyer-Moore 还快,呵呵。长江后浪推前浪。

原始论文:Daniel M. Sunday, A very fast substring search algorithm, Communications of the ACM, v.33 n.8, p.132-142, Aug. 1990

看原始论文的题目,D.M. Sunday 貌似是故意想气气Boyer-Moore 两位大牛似的。呵呵。不过实际上的确Sunday 算法的确比BM 算法要快,而且更简单。

Sunday 的算法思想和Horspool 有些相似,但是。当出现不匹配的时候,却不是去找匹配串中不匹配的字符在模式串的位置,而是直接找最右边对齐的右一位的那个字符在模式串的位置。

比如:

匹配串:abcbc zdxzc

模式串:zbcac

恩,这里我们看到b-a 没有对上,我们就看匹配串中的z 在模式串的位置,然后,嘿嘿。

匹配串:abcbczdxzc

模式串:     zbcac

如果模式串中的没有那个字符怎么办呢?很简单,跳过去呗。

匹配串:abcbc edxzcs

模式串:zbcac

e 不在模式串中出现

那么我们就

匹配串:abcbcedxzcs

模式串:      zbcac

(2009/10/20补充)
RK算法

某一天在图书馆的一本算法分析设计书上翻到的。思路很新颖!和大家分享下。
在串匹配的简单算法中,把文本每m个字符构成的字符段作为一个字段,和模式进行匹配检查。如果能对一个长度为m的字符

串赋以一个Hash函数。那么显然只有那些与模式具有相同hash函数值的文本中的字符串才有可能与模式匹配,这是必要条件

,而没有必要去考虑文本中所有长度为m的字段,因而大大提高了串匹配的速度。因此RK算法的思想和KMP,BM,Sunday等思

路迥然不同!
(事实上,之前的串匹配方法,是将模式串的一个一个字符作为小的特征去分别进行匹配,而RK算法则是将串整体作为一个

特征!难就难在单个字符的特征很容易想得到,整体作为一个特征就没那么容易想得到了)
如果把整体作为一个特征,那么如何快速的求出这个整体特征的特征值??
模式串的特征值仅需求一次即可。对于文本中的任意m个字符构成的字串如何快速的求特征就是个难点了。
抛砖引玉,这里给出一个简单的特征计算。 将字符串的每一个字符看做一个数,那么这个字符串的就是一个数字数组,通

过积分向量可以快速任意一个长度子字符串的向量和。可以把字符串的对应的字符数组的元素和看做这个字符串整体特征。

这个特征是可以再O(1)的时间内求出的。其实原始的RK算法里面是把字符串看做一个26进制数在计算特征的。这里就不啰

嗦了,有兴趣的可以深入查找

aabsee sds 模式串 ees
      ees

发现 see向量和 == ees的向量和
然后就对see和ees做逐个字符的比较。发现不匹配继续往下走
aabsees ds 模式串 ees
        ees
发现 ees向量和 == ees的向量和
然后就对ees和ees做逐个字符的比较。发现匹配OK。

另外还有 字符串匹配自动机 后缀树算法(分在线和非在线两种)等 见如下文章。不能说那个比那个更好,各个算法都有自己的优势及最佳应用场合。参考:
http://blog.csdn.net/yifan403/archive/2009/06/16/4272793.aspx

另外,关于多模式字符串匹配 有AC算法(字符串匹配自动机思想) WM算法(BM在多模式的推广应用)
参考:
http://blog.csdn.net/ijuliet/category/498465.aspx  该女子的blog有很多好文章。

/**********************华丽分割线******************************/
附上sunday代码:
http://hi.baidu.com/kmj0217/blog/item/6f837f2f3da097311e3089cb.html

一种比KMP 和 BM 更高效的匹配算法(如果想看原英文介绍,看下面分割线后的网址)

适用于:模式串较短的情况,最坏时间复杂性为O(N*M),不过一般没这么坏

Sunday 算法其实思想跟BM算法很相似,只不过Sunday算法是从前往后匹配,在匹配失败时关注的是文本串中参加匹配的最末位字符的下一位字符。如果该字符没有在匹配串中出现则直接跳过,即移动步长= 匹配串长度+ 1;否则,同BM算法一样其移动步长=匹配串中最右端的该字符到末尾的距离+1。

 

代码如下:

/*

Sunday-字符串匹配算法 -- 一种优于 KMP 的算法

思想类似于BM 算法,只不过是从左向右匹配

遇到不匹配的看大串中匹配范围之外的右侧第一个字符在小串中的最右位置

另外:采用BM/KMP 的预处理的做法,事先计算好移动步长 ,等到遇到不匹配的值直接使用

*/

#include<iostream>

#include<string.h>

using namespace std;

//一个字符8位 最大256种

#define MAX_CHAR_SIZE 256

 

/*设定每个字符最右移动步长,保存每个字符的移动步长

如果大串中匹配字符的右侧一个字符没在子串中,大串移动步长= 整个串的距离 +1

   如果大串中匹配范围内的右侧一个字符在子串中,大串移动距离= 子串长度 - 这个字符在子串中的位置

*/

int *setCharStep(char *subStr)

{

     int *charStep=new int[MAX_CHAR_SIZE];

     int subStrLen=strlen(subStr);

     for(int i=0;i<MAX_CHAR_SIZE;i++)

             charStep[i]=subStrLen+1;

     //从左向右扫描一遍 保存子串中每个字符所需移动步长

     for(int i=0;i<subStrLen;i++)

     {

            charStep[(unsigned char)subStr[i] ]=subStrLen-i;         

     }

     return charStep;

}

/*

   算法核心思想,从左向右匹配,遇到不匹配的看大串中匹配范围之外的右侧第一个字符在小串中的最右位置

   根据事先计算好的移动步长移动大串指针,直到匹配

*/

int sundaySearch(char *mainStr,char *subStr,int *charStep)

{

     int mainStrLen=strlen(mainStr);

     int subStrLen=strlen(subStr);

     int main_i=0;

     int sub_j=0;

     while(main_i<mainStrLen)

     {                  

            //保存大串每次开始匹配的起始位置,便于移动指针

             int tem=main_i;

             while(sub_j<subStrLen)

             {

                    if(mainStr[main_i] ==   subStr[sub_j])

                    {

                            main_i++;

                            sub_j++;

                            continue;                   

                    }                

                    else{

                        //如果匹配范围外已经找不到右侧第一个字符,则匹配失败

                         if(tem+subStrLen > mainStrLen)

                                     return -1;

                         //否则 移动步长 重新匹配

                         char firstRightChar=mainStr[tem+subStrLen];

                         main_i =tem + charStep[(unsigned char)firstRightChar];

                         sub_j=0;   

                         break;//退出本次失败匹配 重新一轮匹配

                    }  

             }

             if(sub_j == subStrLen)

                       return main_i-subStrLen;

     }

     return -1;

}

int main()

{

         char *mainStr="absaddsasfasdfasdf";

         char *subStr="dd";

         int *charStep=setCharStep(subStr);

         cout<<"位置: "<<sundaySearch(mainStr,subStr,charStep)<<endl;

         system("pause");

         return 0;    

}

 

/*************************************************华丽的分割线***************************************/

算法介绍以及实现伪码:http://www-igm.univ-mlv.fr/~lecroq/string/node19.html

void preQsBc(char *x, int m, int qsBc[]) {
   int i;

   for (i = 0; i < ASIZE; ++i)
      qsBc[i] = m + 1;
   for (i = 0; i < m; ++i)
      qsBc[x[i]] = m - i;
}


void QS(char *x, int m, char *y, int n) {
   int j, qsBc[ASIZE];

   /* Preprocessing */
   preQsBc(x, m, qsBc);

   /* Searching */
   j = 0;
   while (j <= n - m) {
      if (memcmp(x, y + j, m) == 0)
         OUTPUT(j);
      j += qsBc[y[j + m]];               /* shift */
   }
}


// 第三个代码实现,貌似比较高效
http://hi.baidu.com/azuryy/blog/item/10d3d3460b97af0e6b63e5cd.html
头文件定义:
/* Sunday.h */
class Sunday
{
public:
   Sunday();
   ~Sunday();

public:
    int find(const char* pattern, const char* text);

private:
    void preCompute(const char* pattern);

private:
    //Let's assume all characters are all ASCII
    static const int ASSIZE = 128;
    int _td[ASSIZE] ;
    int _patLength;
    int _textLength;
};


源文件
/* Sunday.cpp */

Sunday::Sunday()
{
}

Sunday::~Sunday()
{
}

void Sunday::preCompute(const char* pattern)
{
    for(int i = 0; i < ASSIZE; i++ )
        _td[i] = _patLength + 1;

    const char* p;
    for ( p = pattern; *p; p++)
        _td[*p] = _patLength - (p - pattern);
}

int Sunday::find(const char* pattern, const char* text)
{
    _patLength = strlen( pattern );
    _textLength = strlen( text );

    if ( _patLength <= 0 || _textLength <= 0)
        return -1;

    preCompute( pattern );

    const char *t, *p, *tx = text;

    while (tx + _patLength <= text + _textLength)
    {
        for (p = pattern, t = tx; *p; ++p, ++t)
        {
            if (*p != *t)
                break;
        }
        if (*p == 0)
            return tx-text;
        tx += _td[tx[_patLength]];
    }
    return -1;
}

简单测试下:
int main()

{
    char* text = "blog.csdn,blog.net";
    char* pattern = "csdn,blog"    ;
    Sunday sunday;

    printf("The First Occurence at: %d/n",sunday.find(pattern,text));

    return 1;
}


strstr的实现。
需要说明的是strstr是c语言提供的使用Brute Force实现的字符串匹配,简单、通用是其最大的优点。时间复杂度是O(mn)
// 下面是Microsoft的实现
//经典算法
//比KMP算法简单,没有KMP算法高效
char * __cdecl strstr (
        const char * str1,
        const char * str2
        )
{
        char *cp = (char *) str1;
        char *s1, *s2;
        if ( !*str2 )
            return((char *)str1);
        while (*cp)
        {
                s1 = cp;
                s2 = (char *) str2;
                while ( *s1 && *s2 && !(*s1-*s2) )
                        s1++, s2++;
                if (!*s2)
                        return(cp);
                cp++;
        }
        return(NULL);
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/whoismickey/archive/2009/02/08/3869367.aspx

strstr
  glibc里的strstr函数用的是brute-force(naive)算法,它与其它算法的区别是strstr不对pattern(needle)进行预处理,所以用起来很方便。理论复杂度O
(mn), 实际上,平均复杂度为O(n), 大部分情况下高度优化的算法性能要优于基于自动机的匹配算法,关于串匹配算法可参考http://www-igm.univ-mlv.fr/~lecroq/string/ 。 glibc中使用了(1)Stephen R. van den Berg的实现,在他的基础上,(2)Tor Myklebust http://sources.redhat.com/ml/libc-alpha/2006-07/msg00028.html 给出了更复杂的实现,当然也更高效。
  BF有一个重要性质是事先不用知道串的长度,而基于跳跃的算法是需要用字符串长度来判断结束位置的。如何快速的确定字符串结束位置,可参考http://www.cppblog.com/ant/archive/2007/10/12/32886.html ,写的很仔细。
 将两种思想结合起来,可以做出更快的strstr(3)。约定(1) 为strstrBerg; (2) 为strstrBergo,(3)为lstrstr,(4)为glibc中的strstr,简单测试了一下:
从长度为2k的文本中查找长度为1、2、9的模式串,结果如下
        1               2              9
(1)0.000006 0.000006 0.000012   
(2)0.000007 0.000004 0.000008
(3)0.000002 0.000002 0.000005
(4)0.000005 0.000005 0.000011
下载strstr和测试程序
下载后执行 :
            unzip testStrstr.zip
            cd testStrstr
            make test
基于sse2的strstr函数 是用sse2指令集对strstr的优化
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(笔试前准备)字符串匹配算法总结 的相关文章

  • 找到一系列间隔的最有效分组

    我有一个应用程序 其中有一系列不重叠的固定宽度间隔 每个间隔都有一个给定的键 每个间隔具有相同的宽度 并且可以存在连续的间隔 本质上 我想以最小化单独间隔的数量的方式对间隔和键进行分组 这可以通过合并具有相同键的连续间隔或查找匹配间隔并将它
  • 点集子集的最小周长凸包

    给定平面上的 n 个点 没有 3 个共线 给定数字 k 找到 k 个点的子集 使得 k 个点的凸包在 k 个点的子集的任何凸包中具有最小周长 我可以想到一个简单的方法 运行时间为 O n k k log k 找到大小为 k 的每个子集的凸包
  • 时间复杂度和运行时间有什么区别?

    时间复杂度和运行时间有什么区别 它们是一样的吗 运行时间是指程序运行所需的时间 时间复杂度是对输入大小趋于无穷大时运行时间渐进行为的描述 您可以说运行时间 是 O n 2 或其他什么 因为这是描述复杂性类和大 O 表示法的惯用方式 事实上
  • 在 C++ 中通过引用传递 std 算法谓词

    我正在尝试从 a 中删除元素std list并保留已删除元素的一些统计信息 为此 我使用列表中的remove if 函数 并且我有一个谓词 我想使用这个谓词来收集统计数据 这是谓词的代码 class TestPredicate privat
  • 快速约会算法

    我在一家咨询公司工作 大部分时间都在客户所在地 正因为如此 我很少见到同事 为了更好地了解彼此 我们将安排一个晚宴 会有很多小桌子 方便人们聊天 为了在聚会期间与尽可能多的不同的人交谈 每个人都必须每隔一段时间 比如每小时 换一张桌子 如何
  • 如何有效地找到距给定点最远的点(从一组点中)?

    我正在寻找一种算法或数据结构来解决以下问题 给你一组点 S 然后你会得到另一个点形式的 Q 查询 对于每个查询 找到集合中距离给定点最远的点 集合中最多有 10 5 个点和 10 5 个查询 所有点的坐标都在 0 到 10 5 范围内 我想
  • 如何检查是否存在可能的路径?

    我正在开发一个基于 javascript 的实验性游戏 玩家必须在二维平铺地图上移动才能退出 请随意检查这个小提琴并演奏 http jsfiddle net moonlife 74vLd 我只是随机放置障碍物 但有时障碍物会挡住玩家和出口之
  • 具有多个谓词的 C++11 算法

    功能如std find if来自algorithmheader 确实很有用 但对我来说 一个严重的限制是我只能为每次调用使用 1 个谓词count if 例如给定一个像这样的容器std vector我想同时应用相同的迭代find if 多个
  • 给定一个具有多个重复条目的数组,找到一个重复条目 O(N) 时间和常数空间

    我们得到了一个大小为 N 的数组 其中包含 0 到 N 2 范围内的整数 包括 0 和 N 2 该数组可以有多个重复的条目 我们需要在 O N 时间和常量空间中找到重复条目之一 我正在考虑取数组中所有条目的乘积和总和 以及 0 到 N 2
  • 归并排序中递归树的高度log(n)+1是怎么来的

    我按照 stackoveflow 的建议阅读了一些问题和答案 我正在遵循 cormen 的 算法简介 一书进行自学 那本书里已经解释得很清楚了 但唯一没有解释的是如何在合并排序分析中计算树的高度 如果在后面的章节中对此进行解释的话 我仍然在
  • 举例解释bpe(字节对编码)?

    有人可以帮忙解释一下背后的基本概念吗BPE模型 除了这张纸 https arxiv org abs 1508 07909 目前还没有那么多解释 到目前为止我所知道的是 它通过将罕见和未知的单词编码为子词单元序列来实现开放词汇表上的 NMT
  • 如何对对象进行排序? (画家算法)

    所以我有 4 个矩形形状 我正在尝试应用排序算法 画家算法 https en wikipedia org wiki Painter 27s algorithm 来知道我需要先绘制哪些形状 在 3d 中 然后绘制哪个形状 Note 相机位于右
  • 平铺单纯形噪声?

    我 作为业余爱好者 对伪随机噪声生成很感兴趣 特别是 Perlin 和 Simplex 算法 Simplex 的优点是速度 尤其是在更高的维度上 但 Perlin 可以相对容易地平铺 我想知道是否有人知道平铺单纯形算法 固定维度就好 泛型更
  • 动态规划 (DP) 中的重叠子问题是什么?

    为了使动态规划适用 问题必须具有两个关键属性 最优子结构 and 重叠子问题 1 https en wikipedia org wiki Dynamic programming 对于这个问题 我们只关注后一个属性 有各种不同的定义重叠子问题
  • 归并排序中的递归:两次递归调用

    private void mergesort int low int high line 1 if low lt high line 2 int middle low high 2 line 3 mergesort low middle l
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • 将名称字符串编码为唯一的数字

    我有一大堆名字 数以百万计 他们每个人都有一个名字 一个可选的中间名和一个姓氏 我需要将这些名称编码为唯一代表这些名称的数字 编码应该是一对一的 即一个名称只能与一个数字相关联 一个数字只能与一个名称相关联 对此进行编码的明智方法是什么 我
  • 应用对数来导航树

    我曾经知道一种使用对数从树的一片叶子移动到树的下一个 有序 叶子的方法 我认为它涉及获取 当前 叶子的位置值 排名 并将其用作从根向下到新目标叶子的新遍历的种子 一直使用对数函数测试来确定是否沿着右或左节点向下到达叶子 我已经不记得如何运用
  • 查找其索引的乘积可被另一个数字 X 整除的对的数​​量

    给定一个数组和某个值 X 找到满足以下条件的对的数量 i lt j a i a j and i j X 0 Array size lt 10 5 我想这个问题有一段时间了 但只能想出蛮力解决方案 通过检查所有对 这显然会超时 O N 2 t
  • 欧拉项目 45

    我还不是一名熟练的程序员 但我认为这是一个有趣的问题 我想我应该尝试一下 三角形 五边形 六边形 数字由以下生成 公式 三角形 T n n n 1 2 1 3 6 10 15 五边形 P n n 3n 1 2 1 5 12 22 35 六角

随机推荐

  • 求平均数的几种方法

    平均数 给定两个数a和b 求其平均值 分析 数学运算中一贯的算法是 a b 2 但在c语言中这种算法存在着一定的缺陷 当a和b足够大时 a和b的和就会存在溢出 从而得不到我们想要的结果 c语言中有相应的操作符可达到求平均数的效果 例如 gt
  • 刷脸支付推动产业智慧升级是大势所趋

    近日 浙江省绍兴市上虞区将 刷脸支付 功能向基层延伸 率先实现全区安全范围内的全覆盖 刷脸就医在全国范围内不断实现 在这个充满诱惑的时代 代理刷脸支付这个蓝海项目是许多想做刷脸支付的创业者急需的内容 刷脸支付 这项技术自面世以来就充斥着各种
  • 解决redis-server.exe不是内部或外部命令

    报错 redis server exe不是内部或外部命令 原因 未进入到redis的安装目录下 解决 先找到redis安装路径 复制之后 在终端中输入cd xxxxx redis的安装路径 进入安装目录之后再次输入redis server
  • 深入学习jquery源码之data()

    深入学习jquery源码之data jQuery data element key value 概述 在元素上存放数据 返回jQuery对象 注意 这是一个底层方法 你应当使用 data 来代替 此方法在jQuery 1 8中删除 但你仍然
  • Java面向对象编程

    将N条长度均为M的有序链表进行合并 合并以后的链表也保持有序 时间复杂度为 A O N M logN B O N M C O N D O M 答案 A 下设栈S的初始状态为空 元素a b c d e f依次入栈S 出栈的序列为b d c f
  • 百度网盘登陆验证提示:无法访问此页面,或者二维码显示失败,弹窗显示:无法访问此页面,确保web地址。。。。

    百度网盘登陆验证提示 无法访问此页面 或者二维码显示失败 弹窗显示 无法访问此页面 确保web地址 遇到百度网盘登陆时显示下面的情况 原因 是自己电脑的IE浏览器设置出了问题 没有显示出来应有的验证界面 解决方案 打开电脑的IE浏览器 在右
  • Apex安装失败(笔记记录分享)

    Apex安装失败 笔记记录 1 错误合集 No 1 error detected in the compilation of csrc multi tensor scale kernel cu No 2 module torch nn ha
  • Java long Long

    转载 https www cnblogs com c2g5201314 p 13024261 html 1 long 是 基本类型 Long 是 对象类型 2 long 默认值是 0 Long 默认值是 null 3 比较方法 1 Long
  • LVS 就是这么简单(数字后端物理验证篇)

    LVS 就是这么简单 数字后端物理验证篇 文章右侧广告为官方硬广告 与吾爱IC社区无关 用户勿点 点击进去后出现任何损失与社区无关 今天吾爱 IC 社区小编为大家带来数字 IC 后端实现物理验证中关于 LVS 的主题分享 其实小编一直觉得这
  • 调整echarts中图与legend的距离

    1 正常调整legend的位置 通过X改变横坐标位置 通过Y改变纵轴位置 x 可设定图例在左 右 居中 y 可设定图例在上 下 居中 legend y bottom data 阳性转阴性 阴性转阳性 阳性无症状转有症状 未检测 2 如果觉得
  • STM32F103ZET6【标准库函数开发】------04 串口USART1控制LED

    一 硬件介绍 STM32F103ZET6有5个串口 查看引脚图可以找到对应的IO口分别如下 串口 USART1 USART2 USART3 UART4 UART5 输入 输出方式 USARTx TX PA9 PA2 PB10 PC10 PC
  • forcats

    引子 最近在整理forcats工具包中的函数 发现该包只有fct reorder2 函数的功能不太容易理解 所以单独写一篇推文来介绍它 根据上篇提到的函数分类 它可以归为 调整类别顺序的函数 与它类似的还有一个fct reorder 函数
  • 九龙战登录只显示一个服务器,九龙战登录失败进不去解决办法

    九龙战是腾讯推出的一款三国题材的动作竞技手游 目前已经开启了不删档测试 但是玩家们在游戏中遇到了登录失败进不去的情况 下面小编就为大家介绍一下九龙战登录失败进不去解决办法 首先玩家们要知道九龙战是一款不删档测试不久的游戏 所以在这期间出现什
  • Android基于BroadcastReceiver和Service、SoundPool开发的防过充助手app

    前段时间换了一个小米4C手机 可是发现它的充电充满没有提醒 上一个手机换了就是因为不爱惜电池 让它过充的次数多了 虽然听别人说小米4c手机充电器是智能充电器 有保护作用 但我自己还是不放心 于是就亲手写了一个防过充小应用 已经在使用 可以达
  • 如何使用LaTeX制作PPT?

    作为LaTeX排版软件 LaTeX主要被用来制作书籍和文章 但由于现代LaTeX系统主要以PDF文件为输出方式 授课 演讲用的计算机幻灯片也日益成为LaTeX的一个重要应用 LaTeX中专门用来制作幻灯片的工具有powerdot文档类 pr
  • 探索.NET:​构建现代软件开发的核心框架

    摘要 在现代软件开发领域 选择一个合适的开发框架对于成功构建可靠 高效的应用程序至关重要 NET 读作 dot net 是一个强大而广泛使用的框架 为开发人员提供了丰富的工具和功能 以简化开发过程并加快交付时间 本文将介绍 NET的基本概念
  • 【手撕RPC服务分几步】

    手撕RPC服务分几步 前言 什么是RPC 从被调用方 provider 来说 从调用方 consumer 来说 扩展思考 dubbo架构图 前言 本文试图通过手撕RPC的理论步骤来帮助我们更好的理解其特性 也更好的理解像Dubbo sofa
  • flutter 填坑之旅(dart学习笔记篇)

    俗话说 工欲善其事必先利其器 想要撸flutter app 而不懂 dart 那就像一个不会英语的人在和英国人交流 懵 安装 dart 就不用说了 比较简单dart 官网 https dart dev 安装完成后就开启学习dart 旅程吧
  • MyEclipse配置Tomcat7

    首先我们打开Myeclipse 进入偏好设置window gt perferences 进入偏好设置 perferences 在偏好设置的搜索栏那里输入tomcat查找tomcat 如下图所示 3 我们可以看到搜索到的有四个tomcat项
  • (笔试前准备)字符串匹配算法总结

    我想说一句 我日 我讨厌KMP KMP虽然经典 但是理解起来极其复杂 好不容易理解好了 便起码来巨麻烦 老子就是今天图书馆在写了几个小时才勉强写了一个有bug的 效率不高的KMP 特别是计算next数组的部分 其实 比KMP算法速度快的算法