【算法和数据结构】字符串

回眸只為那壹抹淺笑 提交于 2020-10-09 09:50:03

字符集 charset 和字符编码 character encoding

参考:https://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

字符集是个集合,指明了其支持的所有字符有哪些。字符编码则为字符集中的每个字符指定了一个数字代号,解析的时候把代号替换为具体图形展示给用户。

常用的字符集有:

  • ASCII:包含控制字符,英文,数字等。单字节字符编码,对应的字符编码就是 ASCII 码
  • GB2312
  • Unicode:对应的字符编码有:
    • UTF-8:变长字符编码,可以表示任意 Unicode 编码,兼容 ASCII 编码(是 ASCII 的超集)。
    • UTF-16
    • UTF-32:4字节编码,定长,效率低

字符串是跟字符集绑定在一起的,每个字符串都要按照特定的字符集进行解析,否则就可能看到乱码。

字符串常见操作

通常在每种语言中,用双引号表示字符串,单引号表示字符。

最长公共前缀 LCP(Longest Common Prefix):表示两个字符串从头开始最长的相同子串。

对字符串及字串求哈希

哈希函数特点:

  • 每个哈希函数的值域是固定的
  • 对于不同的输入,其在值域内的分布大致均匀
  • 同一个输入,哈希值唯一
  • 输入的微小变动也会引起哈希函数值的巨大变化
  • 不同输入,其哈希值可能相同,称为碰撞(冲突),但概率较低

字符串的哈希值,通常用 unsigned long long 类型(uint64)。过长时自由溢出即可。

字符串哈希函数

H a s h ( s ) = ∑ i = 0 l e n ( s ) − 1 s [ i ] ∗ p i Hash(s) = \sum_{i=0}^{len(s)-1}{s[i]*p^i} Hash(s)=i=0len(s)1s[i]pi
其中 p 是常数,通常取质数。例如(pow 函数中有变量时,gcc 编译时需要加 -lm 参数):

// c language
int hash(char *str) {
   
   
	int i = 0;
	int h = 0;
	int p = 7;
	while(str[i] != '\0') {
   
   
		h += str[i] * ((int)pow(p, i));
	}
	return h;
}

golang 示例:

package main

import (
    "fmt"
    "math"
)

func hash(str string) int {
   
   
    h := 0.0
    p := 7
    for i, v := range str {
   
   
        h += float64(v) * math.Pow(float64(p), float64(i))
    }
    return int(h)
}

func main() {
   
   
    fmt.Println(hash(""))
    fmt.Println(hash("a"))
    fmt.Println(hash("b"))
    fmt.Println(hash("ab"))
}

后缀哈希函数

H a s h s ( i ) = { 0 , i = l e n ( s ) H a s h s ( i + 1 ) ∗ p + s [ i ] , 0 < = i < l e n ( s ) Hash_s(i) = \left\{ \begin{aligned} 0, i = len(s)\\ Hash_s(i + 1) * p + s[i], 0 <= i < len(s) \end{aligned} \right. Hashs(i)={ 0,i=len(s)Hashs(i+1)p+s[i],0<=i<len(s)

子串哈希函数

Hash_s(i, L) 表示字串 s[i, i + L - 1] 的哈希值,则:
H a s h s ( i , L ) = H a s h s ( i ) − H a s h s ( i + L ) ∗ p L Hash_s(i, L) = Hash_s(i) - Hash_s(i + L) * p^L Hashs(i,L)=Hashs(i)Hashs(i+L)pL

字典树

例子

用字符串哈希执行字符串匹配

给定模式串 t,给定 Q 组询问,每组询问给定一个待匹配串 s。对每组询问分别回答待匹配串 s 是否包含 t 作为字串。

暴力

时间复杂度:O(Q * len(t) * len(s))

字符串哈希

时间复杂度:O(Q * len(s) + len(t))

判断相似字符串

字符串等长且只有一位不同,就称为相似。给定 N 个长度均为 L 且都不相同的字符串,每个串只包含大小写字母和数字,求有多少对相似。N<=30000,L<=200。

暴力

时间复杂度:O(N ^ 2 * L)

字符串哈希

对于每个字符串,枚举删除某一位,并计算哈希

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!