endADT
对于不同的高级语言,其实对串的基本操作会有不同的定义方法
在C#中,字符串操作有ToLower转小写、ToUpper转大写、IndexOf从左查找子串位置
/T为非空串。若主串S中第pos个字符之后存在与T相等的子串,/
/*则返回第一个这样的子串在S中的位置,否则返回0 */
int a Index (String S, String T, int pos )
{
int n,m,i;
String sub;
if (pos > 0)
{
n=StrLength (s) ; /得到主串S的长度/
m = StrLength (T) ; /得到子串T的长度/
i = pos;
while (i <= n-m+1 )
{
SubString (sub,S,i,m) ;/取主串第i个位置/
/*长度与T相等子串给sub */
if (StrCompare (sub,T)!= 0) /★ 如果两串不相等*/
++i;
else /如果两串相等/
return i; /则返回i值/
}
}
return 0; /*若无子串与T相等,返回0 */
}
========================================================================
串的顺序存储结构是用一组地址连续的存储单元来存储串中的字符序列的。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。一般是用定长数组来定义。
既然是定长数组,就存在一个预定义的最大串长度,一般可以将实际的串长度值保存在数组的0下标位置,有的书中也会定义存储在数组的最后一个下标位置。但也有些编程语言不想这么干,觉得存个数字占个空间麻烦。它规定在串值后面加一个不计入串长度的结束标记字符,比如“\0” 来表示串值的终结,这个时候,你要想知道此时的串长度,就需要遍历计算一下才 知道了,其实这还是需要占用一个空间,何必呢。
于是对于串的顺序存储,有一些变化, 串值的存储空间可在程序执行过程中动态分配而得。比如在计算机中存在-一个自由存储区,叫做“堆”。 这个堆可由C语言的动态分配函数malloc ()和free ()来管理。
对于串的链式存储结构,与线性表是相似的,但由于串结构的特殊性,结构中的每个元素数据是一个字符,如果也简单的应用链表存储串值,一个结点对应一个字符,就会存在很大的空间浪费。因此,一个结点可以存放一个字符, 也可以考虑存放多个字符,最后一个结点若是未被占满时,可以用“#”或其他非串值字符补全
当然,这里一个结点存多少个字符才合适就变得很重要,这会直接影响着串处理的效率,需要根据实际情况做出选择。串的链式存储结构除了在连接串与串操作时有一定方便之外,总的来说不如顺序存储灵活,性能也不如顺序存储结构好。
===========================================================================
在文章(相当于一个大串)中找到单词的定位,这种子串的定位操作通常称做串的模式匹配
这是串中很重要的操作之一
我们要找到主串S=“wyjbat”中,找到T = “bat”这个子串的位置。通常要进行下面的步骤。
1.主串S第一位开始,S与T字母进行匹配
2.多次比较从4位开始,S与T,3个字母全匹配,匹配成功
简单的说,就是对主串的每一个字符作为子串开头,与要匹配的字符串进行匹配。对主串做大循环,每个字符开头做T的长度的小循环,直到匹配成功或全部遍历完成为止。
这个算法也太低效了,不玩!!
============================================================================
三个科学家D.E.Knuth、 J.H.Morris 和V.R.Pratt,以他们的姓氏命名的
因为暴力匹配效率太低
比如我们要在主串中匹配子串ABCD,这很简单对吧,常规的思路就是一位一位的匹配(这个思路就是暴力匹配算法)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b9kx80Ep-1637065551742)(C:/Users/Jack/AppData/Roaming/Typora/typora-user-images/image-20211116093132194.png)]
如果对不上了,我们让子串往后移动
上面这种思路可以用代码来实现
/**
-
暴力破解法
-
@param ts 主串
-
@param ps 模式串
-
@return 如果找到,返回在主串中第一个字符出现的下标,否则为-1
*/
public static int bf(String ts, String ps) {
char[] t = ts.toCharArray();
char[] p = ps.toCharArray();
int i = 0; // 主串的位置
int j = 0; // 模式串的位置
while (i < t.length && j < p.length) {
if (t[i] == p[j]) { // 当两个字符相同,就比较下一个
i++;
j++;
} else {
i = i - j + 1; // 一旦不匹配,i后退
j = 0; // j归0
}
}
if (j == p.length) {
return i - j;
} else {
return -1;
}
}
上面的程序没问题,只能说不够好!
主串匹配失败的位置除了第一个A之外再也没有A了,我们为什么知道主串前面只有一个A?因为前三个已经匹配过了啊!它们都是匹配的。
我们可以这样保存i不动,移动j
KMP算法的思想就是利用已经部分匹配的有效信息,保持i指针不回溯,通过修改j指针,让子串尽量的移动到有效的位置!
再详细的可以观看这篇文章,写的很好!
我就不更了,日后在更
(原创)详解KMP算法 - 孤~影 - 博客园 (cnblogs.com)
/通过计算返回子串T的next数组。/
void get_ next ( String T, int *next )
{
int i,j;
i=1;
j=0;
next[1]=0;
while ( i<T[0]) /此处T[0]表示串T的长度/
{
if (j0 11 T[i] T[j]) /* T[i]表示后缀的单个字符,*/
/* T[j]表示前缀的单个字符*/
{
++i;
++j;
next[i]=j;
}
else
j= next[j]; /若字符不相同,则j值回溯/
}
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
++j;
next[i]=j;
}
else
j= next[j]; /若字符不相同,则j值回溯/
}
[外链图片转存中…(img-MO4Z75sP-1714509440376)]
[外链图片转存中…(img-rsLwma5x-1714509440376)]
[外链图片转存中…(img-LmPKGW8g-1714509440376)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新