正则表达式入门指南:基础规则与实例解析

创始人
2024-12-26 22:35:57
0 次浏览
0 评论

正则表达式的基本规则

正则表达式是描述字符串结果的语法规则。
这是一种特定的格式化模式,可以匹配、替换和拦截匹配字符串。
常用的语言基本上都有正则表达式,比如JavaScript、Java等。
其实只要了解了一种语言中正则规则的使用,在其他语言中使用正则规则就不会有问题。
接下来我们来说说正则表达式的一些基本规则。
1.开始和结束定位符(^和$)开始和结束定位符用于描述字符串的开始和结束。
例如:“^”表示要匹配的字符串开头,“$”表示字符串结尾,例如:/^aaa(.*?)bbb$/,表示要匹配以aaa开头的字符串,以bbb结尾,任何字符串都可以居中。
2.选择字符“|”选择表示o的字符。
例如,(my|your)child,mychild和yourchild都可以合并。
3.通用匹配字符“.”表示正则表达式中的任意字符,但只能表示一个。
4.数量匹配运算符“+”、“*”、“?”“*”表示0次以上,“+”表示1次以上,“?”表示1次以上。
代表0或1次。
5、贪婪模式和非贪婪模式上面说了,表示0或1。
如果使用正则表达式进行字符串替换,则贪婪模式替换所有匹配项,非贪婪模式只替换第一个匹配项。
通常添加?表达式之后是非贪婪模式。
完整示例,如何对URLnews.html、news-page-1.html、news-page-2.html、news-page-3使用常规规则。
html表达式全部匹配。
响应:/^新闻(.*?)\.html$/

什么是后缀数组求字符串匹配

后缀数组在字符串处理中,后缀树和仪器后缀数组非常强大。
其中后缀树是大家所熟知的,但是国内关于后缀的资料整理的却很少。
事实上,后缀的顺序非常好,用空间后缀树代替树后缀。
可以说,后缀衣服比电脑游戏中的后缀树更实用。
因此,在本文中,作者想介绍一下集合后缀的基本概念和构造,以及与有序后缀匹配的最长公共介词的构造方法,最后谈谈集合后缀的应用一些例子。
主要概念首先明确一些必要的定义:字符集字符集Σ是建立完整顺序关系的集合。
即Σ中任意两个不同的元素α和β都可以进行大小比较,即α<β,...。
或β<α(即,α>β)。
放置在字符Σ中的元素称为字符。
字符串S由n个字符排序。
S的第i个字符表示为S,子串S的字符串的子串S[i..j],i≤j,表示S的字符串中从i到j的部分,即S,S[i+1],S通序后缀suffix是指从某个位置i开始,到整个字符串末尾结束的特殊子串。
字符串S的从i开始的后缀表示为Suffix(S,i),即Suffix(S,i)=S[i..len(S)]。
至于字符串大小的比较,指的是通常所说的“字典顺序”的比较,即对两个字符串u和v,我从1开始比较后面的u和v,如果相等,我添加1i。
否则,如果uv,则考虑u>v(即v如果i>len(u)或i>len(v)仍然没有变得相似,那么如果len(u)len(v)则u>v。
从比较串数量的定义来看,S起始位置不同的两个后缀u和v的比较结果不可能相等,因为必要条件u=vlen(u)=len(v)在这里是不可能的。
饱足的下面我们约定一个字符和一个字符串S,设置len(S)=n,S[n]='$',即S以特殊字符'$'结尾,'$'小于任何字符在。
除了S[n]之外,S中的其他字符都属于对于由S组成的字符串,从位置i开始的后缀将直接写为suffix(i),省略模块S。
后缀SA的后缀数组是一个一维数组,定义了具体排列1..nSA[1],SA[2],....SA[n],并且保证Suffix(SA)即,将S的n个后缀从小到大划分时,有序后缀的起始位置在SA中连续放置。
RankorderedRankorderedRank=SA-1,即如果SA=j,则Rank[j]=i就足够了。
后缀构造函数如何构造数组?最正确、最简单的方法当然是把后缀S看成是一些普通的和弦,按照常见的和弦模式从小到大排列。
不难看出,这种做法非常别扭,因为它没有利用不同后缀之间的有机联系,因此无法高效。
即使使用了字符串排序效率更高的Multi-keyQuickSort,时间复杂度仍然是O(n2),无法满足我们的需求。
下面介绍一种加倍算法(DoublingAlgorithm),该算法将每个后缀之间进行全连接,将构建后缀数组最坏情况的时间复杂度降低到O(nlogn)。
对于字符串u,我们定义u的一个k介词,这样就定义了k-k介词比较关系仅当uk=vku≤kv当且仅当uk≤vk制作两个字符串。
一个特别的地方是,在比较时,字符串的长度是否小于k并不重要。
变大变小,只要在第k个字符比较结束之前能够得到第一个字符串大小,第二行要么相等,要么更小就可以了。
根据前缀比较运算符的性质,我们可以得到以下最重要的性质:性质1.1对于k≥n,Suffix(i)性质1.2Suffix(i)=2kSuffix(j)相当于Suffix(i)=kSuffix(j)和Suffix(i+k)=kSuffix(j+k)。
性质1.3Suffix(i)<2kSuffix j)等价于Suffix(i)问题就在这里。
当i+k>n或j+k>n时,后缀(i+k)或后缀(j+k)是不定表达式,实际上不需要考虑这个问题,因为此时后缀(i)或后缀(j)的长度不超过k,即它们的k前缀带有'$',所以k前缀的比较结果不能相等,即前k个字符已经可以比较尺寸了;而后面的表达式自然可以被忽略,这也说明了将S设置为'$'的特殊目的。
定义k后缀数组SAk来替换某些数组1..nSAk[1],SAk[2],...SAk[n],使得Suffix(SAk)≤kSuffix(SAk[i+1]);1≤i即在k前缀比较下将所有后缀从小到大排序,并将排序后的后缀的起始位置按照SAk顺序依次放置。
定义Rankk阶顺序。

通过SAk很容易在O(n)时间内找到Rankk。
假设我们求解了SAk和Rankk,我们就可以很容易地求解SA2k和Rank2k,因为根据性质1.2和1.3,2k前缀关系可以由常数个k前缀比较关系组成。
等价表达,数组实际上提供了一种在常数时间内比较关系≤k下的所有排序后缀与一般类型没有区别。
完全等价于每个后缀(i)具有主关键字Rankk和次关键字Rankk[i+k]。
如果使用O(nlogn)类型同样快,则从SAk和Rankk构造SA2k的复杂度为O(nlogn)。
一种更简洁的方法是使用根类型,其复杂度为O(n)。
找到SA2k后,可以在O(n)时间内基于SA2k构建Rank2k。
因此,从SAk和Rankk中取出SA2k和Rank2k可以及时完成。
需要解决的只有一个问题:如何构造SA1和Rank1。
这个问题很简单:因为运算符<1>因此SA1和Rank1的查找时间为O(nlogn)。
当我们找SA1和Rank1后,我们就可以在O(n)内找到SA2和Rank2。
类似地,我们可以在O(n)中找到SA4和Rank4。
SA4和Rank4、SA8和Rank8,...直至SAm和Rankm,其中m=2k且m≥n。
根据性质1.1,SAm和SA是等价的。
这总共需要lognO(n)个过程,因此可以在O(nlogn)时间内计算出SA后缀排列和数组顺序。
现在可以在O(nlogn)时间内计算出最长公共后缀数组SA字符串S。
我们已经可以使用SA做很多事情,例如O(mlogn)时间内的模式匹配,其中m和n分别是模式字符串和要匹配的字符串的长度。
但为了充分利用有组织的后缀的威力,我们还需要一个辅助工具——最长公共前缀(LongestCommonPrefix)。
对两个字符串u和v定义函数lcp(u,v)=max{i|u=iv},即对应的字符从头开始比较u和v,以及对应字符最大的地方。
这些字符串的最长公共前缀称为连续相等。
定义LCP(i,j)=lcp(Suffix(SA),Suffix(SA[j])正整数i,j,其中i,j都是1到n的整数。
长度公共前缀的后缀为double后缀i和j按顺序排列。
遇到的性质:性质2.1LCP(i,j)=LCP(j,i)性质2.2LCP(i,i)=len(Suff(SA))=n-SA+1这两个性质的好处是计算LCP(i,j)时,只需要考虑ij时i可以切换j,当i=j时可以直接输出n-SA+1的结果。
复杂度为O(n),因此我们必须进行适当的预处理来降低计算LCP的成本,经过仔细分析,我们发现LCP函数具有最优性质:-1,k)|i+1≤。
k≤j}(LCPTheor.)要证明LCPTheor,首先证明LCPLma:对于任意1≤i后缀(SA)=u,后缀(SA[j])=v,后缀(SA[k])=w。
由u=LCP(i,j)v变为u=pv;所以Suffix(SA)=pSuffix(SA[k]),即LCP(i,k)≥p。
(1)假设LCP(i,k)=q>p,则u[1]=w[1],u[2]=w[2],...u[q]=w[q]。
min{LCP(i,j),LCP(j,k)}=p表示u[p+1]≠v[p+1]或v[p+1]≠w[q+1],假设u。
[p+1]=x,v[p+1]=y,w[p+1]=z,因为x≤y≤z,并且从p因此,q>p不成立,即LCP(i,k)≤p。
(2)由(1)和(2)可知LCP(i,k)=p=min{LCP(i,j),LCP(j,k)},LCPlemma得证。
因此,LCP定理可以证明如下:当j-i=1且j-i=2时,显然成立。
假设当j-i=m时LCP定理成立。
对于j-(i+1)≤m,LCP(i+1,j)=min{LCP(k-1,k)i|+2≤k≤j},所以当j-i=m+1时,仍然LCP(i,j)=min{LCP(i,i+1),min{LCP(k-1,k)|i+2≤k≤j}}=min{LCP(k-1,k}|i+1≤k≤j)根据数学归纳法,LCP定理成立。
根据LCP定理,得出一个必然的推论:LCPCorollaryi≤j定义一维的高度,height=LCP(i-1,i),1由LCP定理可知,LCP(i,j)=min{height[k]|i+1≤k≤j},即计算LCP(i,j)相当于用one-查询i+上的签名。
维度纵坐标高度1到j范围内所有元素的最小值。
如果数组高度固定,这是一个非常经典的RMQ(RangeMinimumQuery)问题。
RMQ问题可以使用线段树或静态排序树在O(nlogn)时间内进行预处理,然后每次查询都需要O(logn)时间。
(n)时间。
对于固定的弦S,其纵坐标高度显然是固定的。
只要我们能够高效地找到有序高度,那么使用预处理的RMQ方法,每次计算LCP(i,j)的复杂度时间是恒定的。
所以只有一个问题——如何尽可能高效地计算数组的高度。
根据计算后缀着装的经验,不必考虑n个后缀普通字符串相互连接,而是尽量用它们之间的连接作为高度[Rank],即高度h[SA]。
秩h满足性质:性质3:对于i>1且Rank>1,h≥h[i-1]-1。
为了证明性质3,我们需要声明两个事实:取i1,则如下。
两点:Fact1Suffix(i)x(i+1),后缀(j+1))=lcp(后缀(i),后缀(j))-1。
j)))>1表示后缀(i)和后缀(j)的第一比例相同。
,后缀(j)相当于带有后缀(j+1)的α。
比较后缀(i)和后缀(j),第一个字符必须等于α,因此这些比较与(i)等效的后缀。
加上后缀(j),这样Fact1就可以用同样的方法证明。
-1]-1。
=0A[Rank[j]-1].x(k)由Fact1可知,Rank[k+1]因此,根据LCPCorollary,有LCP(Rank-1,Rank)≥LCP(Rank[k+1],Rank)=lcp(Suffix(k+1),Suffix(i))=h[i-1]-1由于h=高度[Rank]=LCP(Rank-1,Rank),最终h≥h[i-1]-1。
根据性质3,可以将i从1连接到n,从而计算h:如果Rank=1,则h=0。
字符比较次数为0。
如果i=1或h[i-1]≤1,则立即比较Suffix(i)和Suffix(Rank-1)从第一个字符开始到不同的字符,并从此计数h的字符数。
比较的是h+1,不超过h-h[i-1]+2。
否则意味着i>1,Rank>1,h[i-1]>1。
]-1个字符,所以比较字符可以从h[i-1]开始,直到某个字符不同,并以此计算。
字符比较的次数为h-h[i-1]+2。
假设SA[1]=p,不难看出字符比较的总数不超过即整个算法的复杂度为O(n)。
考虑阶数h。
基于RMQ方法,前一个时空O(n)时间,任意时刻(i,j)都可以计算出LCP(i,j)。
因为lcp(i),Suffix(j))=LCP(Rank,Rank[j]),LCP(Rank,Rank[j]),LCP(Rank,Rank[j]),所以我们还可以求出之间的最长前缀常数时间内的任意两个后缀。
这就是为什么佩戴后缀能够有力地处理很多字符串问题的主要原因之一。
热门文章
1
Java字符串分割技巧:轻松获取逗号前的... java任意一个字符串,当它碰到第一个逗号时,返回逗号前面的字符串,例如:str...

2
SQL多表连接查询全解析:JOIN语句应... sql多表关联查询在执行SQL多表连接查询时,可以使用JOIN语句将多个表连接在...

3
Java中字符串类型详解:String与... 变量有字符类型,为什么没有字符串类型??基本类型:charshort、int、l...

4
JavaSE与JavaEE:从基础到企业... javase&#160;和javaee的区别?JavaSE和JavaEE...

5
Java程序员面试必知:核心技术问答与技... java编程程序员技术面试常见面试?随着互联网的不断发展,Java开发已经成为很...

6
Java.exe与Javaw.exe:区... 程序中java和javaw有什么区别java和javaw的区别:两者都是Java...

7
深入解析:Java中的javax包及其与... JAVA导入时,什么是javax?awt是java1.0,swing是java2...

8
Java基础教程:深入理解File和Pa... java中if(!file.exists())什么意思?”“在Java >...

9
Java字符串搜索与位置定位技巧解析 在java中求一个字符串在另一个字符串中多次出现的位置。用indexOf方法怎么...

10
Java静态资源加载机制解析:静态方法与... java静态资源(静态方法,静态属性)是程序一运行就加载到jvm中,还是当被调用...