0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于字符串硬核讲解

FPGA之家 来源:FPGA之家 作者:FPGA之家 2022-06-26 10:42 次阅读

1 暴力破解法

在主串A中查找模式串B的出现位置,其中如果A的长度是n,B的长度是m,则n > m。当我们暴力匹配时,在主串A中匹配起始位置分别是 0、1、2….n-m 且长度为 m 的 n-m+1 个子串。

db273a1e-f4e9-11ec-ba43-dac502259ad0.png暴力匹配
对应代码是:
#include
#include
intcnt=0;
intindex(chars[],charsub[])
{
inti=0;
intj=0;
while(i<strlen(s))
{
if(s[i]==sub[j])
{//单个字符相等的话i和j都向后搜索
i++;
j++;
}
else
{//有字符不匹配的话,i从上一次的下一个位置开始,模式串j再从0开始
i=i-j+1;
j=0;
}
if(j==strlen(sub))
{
cnt++;
returni-strlen(sub)+1;
}
}
return-1;
}
intmain()
{
// s="abcdabefgabefa",sub="abe",返回 5。
chars[20],sub[10];
gets(s);
gets(sub);
printf("%d
",cnt);
printf("%d
",index(s,sub));
return0;
}

如果主串是bbb…bbb,模式串是bbbbc,那每个串都要比较m次,一共是(n-m+1)*m次。时间复杂度很大 = O(n*m),一般简单匹配时候可用此法。

2 Rabin-Karp 算法

算法思路:对主串的 n-m+1 个子串分别求哈希值,然后跟模板串的哈希值对比,如果一样再逐个对比字符串是否一样。

db39bb3a-f4e9-11ec-ba43-dac502259ad0.pngRabin-Karp算法
但是中间数据的Hash值计算是可以优化的,我们以简单的字符串匹配举例,把a-z映射到0~25上。然后按照26进制计算一个串的哈希值,比如:
db46d590-f4e9-11ec-ba43-dac502259ad0.pngHash计算
但是你会发现相邻的两个子串数据之间是有重叠的,比如dababc重叠了ab。这样哈希下一个数据的Hash值其实可以借鉴下上一个数据的值推导得出:
db57640a-f4e9-11ec-ba43-dac502259ad0.png优化计算哈希值
RK算法的时间复杂度包含两部分,第一部分是遍历所有子串计算Hash值,时间复杂度是O(n)。第二部分是比较哈希值,这部分时间复杂度也是O(n)。

这个算法的核心就是尽量减少哈希值相等的情况下数据不一样从而进行的比较,所以哈希算法要尽可能的好,如果你感觉用123对应字母abc容易碰撞,那用素数去匹配也是OK的,反正目的是一样的, 你可以认为这是一种取巧的办法来处理字符串匹配问题。

3 Boyer-Moore 算法。

Boyer Moore算法是一种非常高效的字符串匹配算法,它的性能是著名的 KMP 算法的 3 到 4 倍。它不太好理解,但确是工程中使用最多的字符串匹配算法。以前我们匹配字符串的时候是一个个从前往后挪动来逐次比较,BM 算法核心思想是在模式串中某个字符与主串不能匹配时,将模式串往后多滑动几位,来减少不必要的字符比较

db631f7a-f4e9-11ec-ba43-dac502259ad0.png移动比较对比
整体而言BM算法还是挺复杂的相比前面两种,主要包含坏字符规则好后缀规则

3.1 坏字符规则

坏字符规则意思是根据模式串从后往前匹配,当我们发现某个字符没法匹配的时候。我们把这个没有匹配的主串中的字符叫作坏字符

db6dcf10-f4e9-11ec-ba43-dac502259ad0.png坏字符
找到坏字符c后,在模式串中继续查找发现c跟模式串任何字符无法匹配,则可以直接将模式串往后移动3位。继续从模式串尾部对比。
db77731c-f4e9-11ec-ba43-dac502259ad0.png移动2格
此时发现坏字符是g,但在模式串中有个g存在,不能再往后移动3个了,移动的位置是2个。再继续匹配。那有啥规律呢?

发送不匹配时,坏字符对应的模式串字符下标位置Si,如果坏字符在模式串中存在,取从后往前最先出现的坏字符下标记为Xi(取第一个是怕挪动太大咯),如果坏字符在模式串中不存在则Xi = -1。此时模式串往后移动位数= Si - Xi

db88aa4c-f4e9-11ec-ba43-dac502259ad0.png坏字符移动规则
如果碰到极致的主串=cccdcccdcccd,模式串=cccc,那此时时间复杂度是O(n/m)。
db9c903e-f4e9-11ec-ba43-dac502259ad0.png最优解
但是不要高兴太早!下面这种情况可能导致模式串不往后移动,反而往前移动哦!
dbb73bc8-f4e9-11ec-ba43-dac502259ad0.png往前移动?
所以此时BM算法还需要用到好后缀规则

3.2 坏字符代码

为避免每次都拿怀字符从模式串中遍历查找,此时用到散列表将模式串中每个字符及其下标存起来,方便迅速查找。

接下来说下散列表规则,比如一个字符是一个字节,用大小为256的数组记录每个字符在模式串出现位置,数组中存储的是模式串出现的位置,数组下表是字符对应的ASCII值。

dbc14226-f4e9-11ec-ba43-dac502259ad0.png哈希规则 坏字符规则:
//全局变量 SIZE
privatestaticfinalintSIZE=256;
//b=模式串数组,m是模式串数组长度,sl是哈希表,默认-1
privatevoidgenerateBC(char[]b,intm,int[]sl){
for(inti=0;i< SIZE; i++) {
    sl[i] = -1;//初始化sl
}
for(inti=0;i< m; ++i) {
    intascii=(int)b[i];
sl[ascii]=i;
}
}

接下来先不考虑好后缀规则跟坏字符的负数情况,先大致写出 BM 算法代码。

dbd90ad2-f4e9-11ec-ba43-dac502259ad0.png坏字符BM
publicintbm(char[]a,intn,char[]b,intm){
//记录模式串中每个字符最后出现的位置
int[]sl=newint[SIZE];
//构建坏字符哈希表
generateBC(b,m,sl);
//i表示主串与模式串对齐的第一个字符
inti=0;
while(i<= n - m) {
    intj;
for(j=m-1;j>=0;j--){
if(a[i+j]!=b[j])break;
}
if(j< 0){
//匹配成功,返回主串与模式串第一个匹配的字符的位置
returni;
}
//将模式串往后滑动j-bc[(int)a[i+j]]位
i=i+(j-sl[(int)a[i+j]]);
}
return-1;
}

3.3 好后缀规则

好后缀跟坏后缀道理类似,从后往前匹配,直到遇到不匹配的字符x,那主串x之前的就叫好后缀

dbe9e0e6-f4e9-11ec-ba43-dac502259ad0.png好后缀定义
此时移动的规则如下:
  1. 如果好后缀在模式串中找到了,用x框起来,然后将x框跟好后缀对齐继续匹配。

    dbf9aeae-f4e9-11ec-ba43-dac502259ad0.png找到了移动规则
  2. 找不到的时候,如果直接移动长度是模式串m位,那极有可能过度了!而过度移动存在的原因就是,比如你找了好后缀u,u在模式串中整体没找到,但是u的子串d是可以跟模式串匹配上的啊。

    dc0d6386-f4e9-11ec-ba43-dac502259ad0.png过度移动

所以此时还要看好后缀的后缀子串是否跟模式串中的前缀子串匹配,从好后缀串的后后缀子串中找个最长能跟模式串的前缀子串匹配的然后滑动到一起,比如上面的d。

然后分别计算坏字符往后滑动位数跟好后缀往后滑动此时,两者取其大作为模式串往后滑动位数,这种情况下还可以避免坏字符的负数情况。

3.4 好后缀代码

好后缀的核心其实就在于两点

  1. 在模式串中,查找跟好后缀匹配的另一个子串。

  2. 在好后缀的后缀子串中,查找最长的、能跟模式串前缀子串匹配的后缀子串。

3.4.1 预处理工作

上面两个核心点可以在代码层面用暴力解决,但太耗时!我们可以在匹配前通过预处理模式串,预先计算好模式串的每个后缀子串,对应的另一个可匹配子串的位置。

先看如何表示模式串中不同的后缀子串,因为后缀子串的最后个字符下标为m-1,我们只需记录后缀子串长度即可,通过长度可以确定一个唯一的后缀子串。

dc202c50-f4e9-11ec-ba43-dac502259ad0.png子串表示
再引入关键的变量suffix数组。suffix 数组的index表示后缀子串的长度。下标对应的数组值存储的是
好后缀在模式串中匹配的起始下标值:
dc2e78f0-f4e9-11ec-ba43-dac502259ad0.pngsuffix数组定义
比如此处后缀子串c在模式串中另一个匹配开始位置为2, 后缀子串bc在模式串中另一个匹配开始位置为1 后缀子串dbc在模式串中另一个匹配开始位置为0, 后缀子串cdbc在模式串中只出现了一次,所以为-1。
dc404bf2-f4e9-11ec-ba43-dac502259ad0.pngprefix 数组
这里需注意,我们不仅要在模式串中查找跟好后缀匹配的另一个子串,还要在好后缀的后缀子串中查找最长的能跟模式串前缀子串匹配的后缀子串。比如下面:
dc5200a4-f4e9-11ec-ba43-dac502259ad0.png最长模式匹配

suffix只能查找跟好后缀匹配的另一个子串。但还需要个 boolean 类型的prefix数组来记录模式串的后缀子串是否能匹配模式串的前缀子串。

接下来重点看下如何填充suffixprefix数组,拿下标从 0 到 i 的子串与整个模式串,求公共后缀子串,其中i=[0,m-2]。如果公共后缀子串的长度是 k,就suffix[k]=j,其中 j 表示公共后缀子串的起始下标。如果 j = 0,说明公共后缀子串也是模式串的前缀子串,此时 prefix[k]=true。

dc615478-f4e9-11ec-ba43-dac502259ad0.pngsuffix跟prefix数组
//b=模式串,m=模式串长度,suffix,prefix数组如上定义
privatevoidgenerateGS(char[]b,intm,int[]suffix,boolean[]prefix){
//初始化
for(inti=0;i< m; i++){
suffix[i]=-1;
prefix[i]=false;
}
//b[0,i]
for(inti=0;i< m - 1;i++){
intj=i;
//公共后缀子串长度
intk=0;
//与b[0, m-1]求公共后缀子串,并且会有覆盖现象产生。
while(j>=0&&b[j]==b[m-1-k]){
--j;
++k;
//j+1表示公共后缀子串在b[0,i]中的起始下标
suffix[k]=j+1;
}
//如果公共后缀子串也是模式串的前缀子串
if(j==-1)prefix[k]=true;
}
}
3.4.2 正式代码

有了suffixprefix数组后,看下移动规则。假设好后缀串长度=k,如果k != 0,说明有好后缀,接下来通过suffix[k]的值来判断如何移动。

  1. suffix[k] != -1,不等于时说明匹配上了,模式串后移 j-suffix[k]+1 位,其中 j 表示坏字符对应的模式串中的字符下标。

  2. suffix[k] = -1,等于时说明好后缀没匹配上,那就看下子串的匹配情况,好后缀的后缀子串长度是 b[r, m-1],其中 r = [j+2,m-1],后缀子串长度 k=m-r,如果 prefix[k] = true,说明长度为 k 的后缀子串有可匹配的前缀子串,这样我们可以把模式串后移 r 位。

  3. 如果都没匹配上,那就直接将模式串后移m位。

    // a跟n 分别表示主串跟主串长度。
    // b跟m 分别表示模式串跟模式串长度。
    publicintbm(char[]a,intn,char[]b,intm){
    //用来记录模式串中每个字符最后出现的位置
    int[]sl=newint[SIZE];
    //构建坏字符哈希表
    generateBC(b,m,sl);
    int[]suffix=newint[m];
    boolean[]prefix=newboolean[m];
    //构建suffix跟prefix数组
    generateGS(b,m,suffix,prefix);
    inti=0;//j表示主串与模式串匹配的第一个字符
    while(i<= n - m) {
        intj;
    //模式串从后往前匹配
    for(j=m-1;j>=0;--j){
    //坏字符对应模式串中的下标是j
    if(a[i+j]!=b[j])break;
    }
    if(j< 0){
    //匹配OK,返回主串与模式串第一个匹配的字符的位置
    returni;
    }
    //坏字符计算所得需移动长度
    intx=j-sl[(int)a[i+j]];
    inty=0;
    //j< m-1  说明有好的匹配上了
    if(j< m-1){
    y=moveByGS(j,m,suffix,prefix);
    }
    i=i+Math.max(x,y);
    }
    return-1;
    }
    
    //j=坏字符对应的模式串中的字符下标
    //m=模式串长度
    privateintmoveByGS(intj,intm,int[]suffix,boolean[]prefix){
    //好后缀长度
    intk=m-1-j;
    if(suffix[k]!=-1){
    //好后缀可以匹配上,返回需移动长度
    returnj-suffix[k]+1;
    }
    //有匹配到好后缀子串的模式串前缀子串
    for(intr=j+2;r<= m-1;++r){
    if(prefix[m-r]==true){
    returnr;
    }
    }
    //没找到直接移动最大值
    returnm;
    }
    

3.5 复杂度分析

整个BM算法用到了额外的 sl、suffix、prefix三个数组,其中sl数组大小跟字符集大小有关,suffix 数组和 prefix 数组的大小跟模式串长度 m 有关。如果处理字符集很大的字符串匹配问题,bc 数组对内存的消耗就会比较多。

因为好后缀和坏字符规则是独立的,如果我们运行的环境对内存要求苛刻,可以只使用好后缀规则,不使用坏字符规则,这样就可以避免 bc 数组过多的内存消耗。不过,单纯使用好后缀规则的 BM 算法效率就会下降一些了。

BM 算法的时间复杂度分析起来是非常复杂,一般在3n~5n之间。

4 KMP 算法

KMP算法跟BM算法类似,从前往后匹配,把能匹配上的叫好前缀,不能匹配上的叫坏字符

dc6aee3e-f4e9-11ec-ba43-dac502259ad0.pngKMP匹配定义
遇到坏字符后就要进行主串好前缀后缀子串跟模式串的前缀子串进行对比,问题是对于已经比对过的好前缀,能否找到一种规律,将模式串一次性滑动很多位?
dc7b45d6-f4e9-11ec-ba43-dac502259ad0.png暴力破解

思路是将主串中好前缀的后缀子串和模式串中好前缀的前缀子串进行对比,获取模式串中最大可以匹配的前缀子串。一般把好前缀的所有后缀子串中,最长的可匹配前缀子串的那个后缀子串,叫作最长可匹配后缀子串。对应的前缀子串,叫作最长可匹配前缀子串。假如现在最长可匹配后缀子串 = u,最长可匹配前缀子串 = v,获得uv的长度为k,此时在主串中坏字符位置为i,模式串中为j,接下来将模式串后移j-k位,然后将待比较的模式串位置j = j-k进行比较。

dc86fca0-f4e9-11ec-ba43-dac502259ad0.pngKMP算法移动

4.1 Next 数组存在意义

那最长可匹配前缀跟后缀我们用模式串就可以求解了。仿照BM算法,预先计算好就行。在KMP算法中提前构造个next数组。其中next数组的下标用来存储前缀子串最后一个数据的index,对应的value保存的是这个字符串的后缀子串集合跟前缀子串集合的交集。

干说可能不太好理解,我们以"abababca"为例。它的部分匹配表(Partial Match Table)数组如下:

dc92760c-f4e9-11ec-ba43-dac502259ad0.pngNext数组
接下来对value值的获取进行解释,如果字符串A和B,存在A=BS,其中S是任意的非空字符串,那就称B为A的前缀。例如”what”的前缀包括{"w","wh","wha"},我们把所有前缀组成的字符串的前缀集合。同样可以定义后缀A=SB, 其中S是任意的非空字符串,那就称B为A的后缀,例如"Potter"的后缀包括{"otter", "tter", "ter", "er", "r"},然后把所有后缀组成字符串的后缀集合。要注意字符串本身并不是自己的后缀

PMT数组中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。例如,对于"aba",它的前缀集合为{"a", "ab"},后缀集合为{"ba", "a"}。两个集合的交集为{"a"},那么长度最长的元素就是字符串"a"了,长度为1,所以"aba"的Next数组value = 1,同理对于"ababa",它的前缀集合为{"a", "ab", "aba", "abab"},它的后缀集合为{"baba", "aba", "ba", "a"}, 两个集合的交集为{"a", "aba"},其中最长的元素为"aba",长度为3。

我们以主串"ababababca"中查找模式串"abababca"为例,如果在j处字符不匹配了,那在模式串[0,j-1]的数据串"ababab"中,前缀集合跟后缀集合的交集最大值就是长度为4的"abab"。

dc9b1582-f4e9-11ec-ba43-dac502259ad0.pngPMT数组使用方法
基于此就可以使用PMT加速字符串的查找了。我们看到如果是在j位失配,那么影响j 指针回溯的位置的其实是第 j−1 位的 PMT 值,但是编程中为了方便一般不直接使用PMT数组而是使用Next数组,Next数组的value其实就是存储的这个前缀的最长可以匹配前缀子串的结尾字符下标,其中如果匹配不到用-1代替。
dca6e6aa-f4e9-11ec-ba43-dac502259ad0.pngNext数组使用

4.2 KMP 匹配代码

// a =主串,n=主串长度。b =模式串,m =模式串长度
publicstaticintkmp(char[]a,intn,char[]b,intm){
int[]next=getNexts(b,m);
intj=0;
for(inti=0;i< n; ++i) {
    while(j>0&&a[i]!=b[j]){
j=next[j-1]+1;//发现不一样则保持i不变j进行移动
}
if(a[i]==b[j]){
++j;
}
if(j==m){//找到匹配模式串的了
returni-m+1;
}
}
return-1;
}

至此你会发现只要搞明白了PMT存在的意义,然后顺着思路推Next数组即可。

4.3 Next 数组求解

当要计算next[i]时,前面计算过的next[0~i-1]是否可以被用来快速推导出next[i]呢?

情况一:如果next[i-1] = k-1,那此时b[0,i-1]的最长可匹配前缀子串是b[0,k-1],如果b[0,i-1]的下个字符b[i]跟b[0,k-1]的下个字符b[k]相等,那next[i] = k。

dcb9405c-f4e9-11ec-ba43-dac502259ad0.png
情况二:假设b[0,i]最长可用后缀子串是b[r,i],那b[r,i-1]肯定是b[0,i-1]的可匹配后缀子串,但不一定是最长可匹配后缀子串。比如字符串b = "dexdecdexdex",此时最长可匹配后缀子串是"dex",b去掉最后的'x'成为B,此时虽然"de"是B的可匹配后缀子串,但"dexde"才是最长后缀子串!也就是说b[0, i-1]最长可匹配后缀子串对应的模式串的前缀子串的下一个字符并不等于 b[i]。
dcc496e6-f4e9-11ec-ba43-dac502259ad0.png
那此时看下b[0,i-1]的次长可匹配后缀子串b[x,i-1]对应的可匹配前缀子串b[0,i-1-x] 的下个字符b[i-x] 是否等于b[i],相等那b[0,i]的最长可匹配后缀子串是b[x,i]。
dcd1be84-f4e9-11ec-ba43-dac502259ad0.png

那我们来求 b[0, i-1]的次长可匹配后缀子串呢?次长可匹配后缀子串一定被包含在最长可匹配后缀子串中,而最长可匹配后缀子串又对应最长可匹配前缀子串 b[0, y]。此时查找 b[0, i-1]的次长可匹配后缀子串变成了查找b[0, y]的最长匹配后缀子串的问题。

按此思路考察完所有的 b[0, i-1]的可匹配后缀子串 b[y, i-1],直到找到一个可匹配的后缀子串,它对应的前缀子串的下一个字符等于 b[i],那这个 b[y, i]就是 b[0, i]的最长可匹配后缀子串。

dcdf81d6-f4e9-11ec-ba43-dac502259ad0.png
//b=模式串,m=模式串的长度
privatestaticint[]getNexts(char[]b,intm){
int[]next=newint[m];
next[0]=-1;
intk=-1;
for(inti=1;i< m; ++i) {
    while(k!=-1&&b[k+1]!=b[i]){
k=next[k];
//因为前一个的最长串的下一个字符不与最后一个相等,需要找前一个的次长串,
//问题就变成了求0到next(k)的最长串,如果下个字符与最后一个不等,
//继续求次长串,也就是下一个next(k),直到找到,或者完全没有
//最好结合前面的图来看
}
if(b[k+1]==b[i]){
++k;//字符串相等则看下一个
}
next[i]=k;//数组赋值
}
returnnext;
}

KMP空间复杂度:该算法只需要一个额外的 next 数组,数组的大小跟模式串相同。所以空间复杂度是 O(m),m 表示模式串的长度。
KMP时间复杂度:next 数组计算的时间复杂度是 O(m) + 匹配时候时间复杂度是 O(n) = O(m+n)

至此,常见的字符串匹配算法正式讲解完毕,其实前面说的都是一个主串,一个模式串。

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 字符串
    +关注

    关注

    1

    文章

    577

    浏览量

    20485

原文标题:字符串硬核讲解

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    labview字符串数组转化为数值数组

    在LabVIEW中,将字符串数组转换为数值数组是一项常见的任务,尤其是在处理数据采集、信号处理或用户输入时。 1. 理解LabVIEW的数据类型 在开始之前,了解LabVIEW中的数据类型是非
    的头像 发表于 09-04 17:47 1741次阅读

    labview字符串如何转换为16进制字符串

    在LabVIEW中,将字符串转换为16进制字符串是一个常见的需求,尤其是在处理数据通信和硬件接口时。LabVIEW提供了多种方法来实现这一转换,包括使用内置函数、编写VI(Virtual
    的头像 发表于 09-04 15:54 1806次阅读

    labview中常用的字符串函数有哪些?

    在LabVIEW中,常用的字符串函数广泛覆盖了对字符串的各种操作,包括但不限于格式化、搜索、替换、连接、计算长度等。以下是一些常用的字符串函数及其简要说明: 字符串长度(String
    的头像 发表于 09-04 15:43 508次阅读

    labview字符串的四种表示各有什么特点

    。在LabVIEW中,字符串是一种基本的数据类型,用于表示文本信息。字符串在LabVIEW中有多种表示方式,每种方式都有其特定的应用场景和特点。以下是对LabVIEW中四种字符串表示方式的分析: 1.
    的头像 发表于 09-04 15:40 411次阅读

    C语言字符串编译函数介绍

    在C语言中,字符串实际上是使用null字符O'终止的一维字符数组。因此,一个以null结尾的字符串,包含了组成字符串
    的头像 发表于 03-07 16:18 475次阅读
    C语言<b class='flag-5'>字符串</b>编译函数介绍

    labview扫描字符串怎么用

    LabVIEW 是一种流程化编程语言和开发环境,主要用于控制、测量和监测系统。在 LabVIEW 中,扫描字符串是一项常见的任务,它允许用户按照一定的模式从输入字符串中提取所需的信息。下面我将详细
    的头像 发表于 12-29 10:12 1856次阅读

    KUKA 机器人系统函数StrFind()-在字符串里查找

    搜索字符串变量 用功能 StrFind() 可以搜索字符串变量的字符串。 Result = StrFind( StartAt, StrVar[], StrFind[], CaseSens )
    的头像 发表于 12-27 10:36 625次阅读

    labview扫描字符串怎么用

    LabVIEW是一种图形化编程语言,用于开发控制、测量和监控系统。虽然它主要用于工程和科学领域,但也可以用于处理文本和字符串。 在LabVIEW中,可以使用字符串处理函数来扫描字符串。以下是一些常用
    的头像 发表于 12-26 16:58 1868次阅读

    labview中怎么对字符串中的进行实时处理

    LabVIEW是一种用于开发控制、测试和测量系统的可视化编程环境,它提供了许多处理字符串的功能。在LabVIEW中,可以使用不同的函数和工具来实时处理字符串。下面我将详细介绍一些常见的方法和技术
    的头像 发表于 12-26 14:12 1759次阅读

    oracle字符串split成多个

    Oracle是一种广泛使用的关系型数据库管理系统,它提供了许多强大的功能和函数,用于处理和操作数据。其中之一就是字符串分割(split)方法,该方法用于将一个字符串按照指定的分隔符分割成多个子字符串
    的头像 发表于 12-06 09:54 5106次阅读

    oracle判断字符串包含某个字符

    字符串操作是任何编程语言中都非常重要的一部分,Oracle数据库作为目前最常用的关系型数据库之一,也提供了丰富的字符串操作函数和方法。在本文中,我们将详细解析如何在Oracle中判断一个字符串是否
    的头像 发表于 12-06 09:53 1.4w次阅读

    oracle中拼接字符串函数

    在Oracle中,我们可以使用 CONCAT 函数来拼接字符串。CONCAT 函数接受两个参数,它将这两个参数连接起来并返回相应的字符串结果。 语法示例: CONCAT(string1
    的头像 发表于 12-06 09:49 2803次阅读

    字符数组和字符串有没有区别?

    字符数组和字符串有没有区别?
    的头像 发表于 11-30 16:39 620次阅读

    MySQL替换字符串函数REPLACE

    MySQL是目前非常流行的开源数据库管理系统之一,它具有强大的功能和性能。其中之一的字符串函数REPLACE,可以用于替换字符串中的指定字符字符串。在本文中,我们将详细讨论MySQL
    的头像 发表于 11-30 10:44 1475次阅读

    c语言字符串定义

    C语言是一种强大而广泛使用的编程语言,字符串是其中一个非常重要的概念。在C语言中,字符串是由一系列字符组成的数组,它可以表示文本、数字等各种类型的数据。在本文中,我们将详尽、详实、细致地介绍C语言
    的头像 发表于 11-24 10:02 1789次阅读