字符串处理

来源:互联网 发布:淘宝大众评审 编辑:程序博客网 时间:2024/06/05 16:53

一、串的5种基本操作

1.串赋值(=)
2.串比较(!= ==)
3.求串长(length())
4.串连接(+)
5.求子串(substr())

串操作的本质是字符类型数组的复制,C++中的string类可以提供方便快捷的串操作。

二、其他操作

1.插入(insert())
已知插入点,可通过对串插入点前后分别取子串操作,再通过串连接操作实现。
2.删除(erase())
已知删除部分,可通过对串的删除部分前后分别取子串操作,再通过串连接操作实现。
3.替换(replace())
已知替换部分,可通过删除操作+插入操作实现。

三、模式匹配

1.简单的模式匹配算法

//在串str1中从k位置开始匹配str2,匹配成功返回首字母地址,匹配失败返回-1。//a为str1的长度,b为str2的长度int i,j;for(i=k;i<a-b;i++){    for(j=0;j<b;j++){        if(str1[i+j]!=str2[j]){            break;        }    }    if(j==b){        return i;    }}return -1;

2.KMP算法
(1)计算next(j)的算法:

//j的作用是遍历模式串//lengthP是模式串的长度int j=0,k=-1,lengthP=curLength;//next[i]表示在前i个字符中,前后串匹配的长度。//在该算法中,可理解成已匹配部分的后面一个字符的下标。//后面一个字符的下标刚好为前面已匹配部分的长度。next[0]=-1;while(j<lengthP){//如果后一个字符匹配,则i和k均往后移,判断下一个字符是否匹配    if(k==-1 || ch[j]==ch[k]){        j++;k++;        next[j]=k;    }    else{//如果后面一个字符不匹配,则i不变,k变为前k个字符中已匹配部分的下一个字符的下标。//即next[k]//比较该字符和后面一个字符是否匹配,重复操作,直到匹配或-1结束。        k=next[k];    }}

该算法理解不易用语言表示,请参看https://www.bilibili.com/video/av3246487/?from=search&seid=17173603269940723925。
该算法重点理解next[i]存放的是前i个字符中,前后匹配部分的后一个字符的下标,也可以理解为前i个字符中匹配部分长度。
运用的思想是,较长的字符串由于最后一个字符不匹配,那么就从该字符串中找到最长的已匹配的字符串,判断字符串的后一个字符与当前字符是否匹配。

(2)主算法:

//posP为模式串的扫描指针,posT为目标串的扫描指针int posP=0,posT=k;//lengthP为模式串的长度,lengthT为目标串的长度int lengthP = pat.curLength;int lengthT = curLength;//下面做法与求next[i]相同,只不过求next[i]是模式串与自身匹配while(posP<lengthP && posT< lengthT){    if(posP==-1 || pat.ch[posP]==ch[posT]){        posP++;posT++;    }    else{        //next[posP]表示模式串前posP个字符中,前缀的后一个字符的下标。        //其中前缀指模式串前posP个字符中前面与后面最大相同部分。        posP=next[posP];    }}//posP<lengthP表示目标串先于模式串扫描完。if(posP<lengthP){    return -1;}else{    //此时posT指向满足模式串部分的下一个字符,减去模式串长度即为满足部分的首字符下标。    return posT-lengthP;}

3.小结
字符串操作中最难的部分就是模式匹配中的KMP算法,如果不考虑效率问题,可以使用简单模式匹配算法实现该功能。
KMP算法的关键在于理解next[i]中存放的是什么。个人对这个有2种理解:第一、next[i]表示前i个字符中前面与后面最大相同部分的长度;第二、next[i]表示前i个字符中前面与后面最大相同部分的下一个字符的下标。
在代码实现中,我认为第二种更容易理解代码。
能力有限,KMP算法这部分真的很难仅通过文字来表述,个人又嫌作图麻烦,所以只能讲到这种程度了。

四、C++中的string类

总结一下,字符串的本质就是把一堆字符类型的东西放在了一起而已(不管是用数组、动态数组还是链表等)。对字符串的操作,其本质就是对单个字符的操作(便于理解可以直接想像成字符数组)。上面讲了这么多,只是想把各种操作的实现归结于循环和选择这两个本质结构。

对于使用而言,C++的string类显得十分方便。
1.赋值和复制(=)
2.判断相等或不等(!= ==)
3.字符串长度(length())
4.连接(+)
5.取子串(substr())

6.存取单一字符([ ])
7.查找某个字符或字符串(find())
8.插入(insert())
9.删除(erase())
10.替换(replace())
上述函数都有好几种参数形式,熟练掌握适合自己的参数形式,可以在字符串处理上,大幅度提高效率。

原创粉丝点击