字符串也叫串,是由字符组成的有限序列,是一种常用的非数值数据
串的逻辑结构是线性表,其每个数据元素都是一个字符
串主要是对子串进行操作
通常采用顺序存储结构存储
为什么不用链式呢?字符串都是一段序列,直接存一快方便一点,而且一般串都比较短
字符串中任意个连续字符组成的子序列称为字符串的子串
空串是任意串的子串
每个字符串都是其自身的字串
两个串相等是指串长度相同并且对应位置上的字符也相同
两个串的大小由对应位置上的首个不同字符的大小决定,字符比较顺序是从头开始依次向后
当两个串的长度不等而对应位置上的字符都相同时较长的串定义为较大

顺序串

class SqString:
    def __init__(self,obj=None):
        # 构造空串
        if obj is None:
            self.strValue = [] # 字符数组存放串值
            self.curLen = 0 # 当前串的长度
        elif isinstance(obj,str): # 以字符串构造串
            self.curLen = len(obj)
            self.strValue = [None] * self.curLen
            for i in range(self.curLen):
                self.strValue[i] = obj[i]
        elif isinstance(obj,list):# 以字符列表构造串
            self.curLen = len(obj)
            self.strValue = [None] * self.curLen
            for i in range(self.curLen):
                self.strValue[i] = obj[i]

    def clear(self):
        """将字符串置成空串"""
        self.curLen = 0

    def isEmpty(self):
        """判断是否为空串"""
        return self.curLen == 0

    def length(self):
        """返回串的长度"""
        return self.curLen

    def charAt(self,i):
        """读取并返回串中的第i个数据元素"""
        if i < 0 or i >= self.curLen:
            return 'no'
        return self.strValue[i]

    def allocate(self,newCapacity):
        """将串的长度扩充为newCapactiy"""
        temp = self.strValue
        self.strValue = [None] * newCapacity
        for i in range(self.curLen):
            self.strValue = temp[i]

    def subString(self,begin,end):
        """返回位序号从begin到end-1的字串"""
        if begin < 0 or begin >= end or end > self.curLen:
            return 'no'
        temp = [None] * (end-begin)
        for i in range(begin,end)
            temp[i - begin] = self.strValue[i] # 复制子串
        return SqString(temp)

    def insert(self,i,str):
        """在第i个字符之前插入子串"""
        if i < 0 or i > self.curLen:
            return 'no'
        length = self.length()
        newCapacity = self.curLen + length
        self.allocate(newCapacity)
        for j in range(self.curLen-1,i-1,-1):
            self.strValue[j+length] = self.strValue[j]
        for j in range(i,i+length):
            self.strValue[j] = self.charAt(j-1)
        self.curLen = newCapacity


    def delete(self,begin,end):
        """删除位序号从begin到end-1的子串"""
        if begin < 0 or begin >= end or end > self.curLen:
            return 'no'
        for i in range(begin,end):
            self.strValue[i] = self.strValue[i+end-begin]
        self.curLen = self.curLen - end + begin


    def concat(self,str):
        """将str连接到字符串的后面"""
        pass

    def compareTo(self,str):
        """比较str和当前字符串的大小"""
        pass

    def indexOf(self,str,begin):
        """从位序号为begin的字符开始搜索与str相等的子串"""
        pass

    def display(self):
        """打印字符串"""
        for i in range(self.curLen):
            print(self.strValue[i])

链串

链串由一系列大小相同的节点组成
每个节点的数据域可以是一个或者多个字符
每个数据域为单个字符,单字符链表
每个节点的数据域为多个字符,为块链表
块链表中每个节点的数据域不一定被字符占满

串的模式匹配

串的模式匹配也叫查找定位,指的是在当前串中寻找模式串的过程

Brute Force算法

从主串的第一个字符开始和模式串的第一个字符进行比较,若相等,则继续比较后续字符,否则从主串的第二个字符开始重新和模式串进行匹配,以此类推,直到模式串中的每个字符依次与主串的字符相等,匹配成功

def BF(self,str,begin):
        if str.length() <= self.curLen and str is not None and self.curLen > 0:
            i = begin
            length = str.length()
            while i<= self.curLen - length:
                if str.charAt(j) != self.strValue[j+1]
                    i += 1
                    break
                elif j == length - 1:
                    return i
        return -1

Brute Force算法的实现非常简单,但是效率非常低,m为模式串的长度,n为主串的长度
最好情况:第一次匹配成功,比较次数为模式串的长度m,时间复杂度为O(m)
最坏情况:每次匹配比较至模式串的最后一个字符,并且比较了目标串中所有长度为m的子串,此时的时间复杂度欸O(m*n)

kmp算法

当某次匹配失败时,主串的开始比较位置不回退,而是利用部分字符匹配的结果将模式串向后移动较远的距离后在继续进行比较

def next(p):
        next = [0] * p.length()
        k = 0 # 模式串指针
        j = 1 # 主串指针
        next[0] = -1
        next[1] = 0
        while j < p.length() -1:
            if p.charAt(j) == p.charAt(k):
                next[j + 1] = k + 1
                k += 1
                j += 1
            elif k == 0:
                next[j + 1] = 0
                j += 1
            else:
                k = next[k]
        return next

    def KMP(self,p,begin):
        next = SqString.next(p) # 计算next值
        i = begin # i 为主串的字符指针
        j = 0
        while i < self.curLen and j < p.length():
            if j == -1 or self.strValue[i] == p.charAt(j):
                # 比较的字符相等或者比较主串的下一个字符
                i += 1
                j += 1
            else:
                j = next[j]
        if j == p.length():
            return i - j # 匹配
        else:
            return -1