字符串算法入门笔记

FinderHT / 2023-07-15 / 原文

zhx:什么AC自动机,KMP算法从来不会考
zhx:不推荐用 string,因为麻烦

读ans入一个字符串

char s[MAXN];
cin>>s+1;//从s[1]开始读入,操作时方便

在遍历字符串时,我们要先把字符串长度存下来,因为计算字符串长度的函数 strlen 的时间复杂度为\(O(长度)\),如果写成

for(int i=1;i<=strlen(s+1);i++)

就很容易TLE;
因此

int len=strlen(s+1);
for(int i=1;i<=len;i++)

比较字符串:
朴素想法:我们把每个字符串的每一位都进行比较,设字符串长度为 \(k\),比较一次的复杂度为 \(O(k)\)
当有很多字符串的时候时间复杂度会很大,所以我们用一个神奇的字符串算法 字符串哈希。

字符串 -> 数
如:abc -> 123
问题 哈希碰撞:
例如:
ka -> 111
aaa-> 111

我们发现明明这两个字符串不一样,但他们的hash值是一样的,这时就发生了哈希碰撞。

单模哈希法
\(27\) 进制(别的其实也可以)存储下来字符串。但是由于数太大了,所以我们定义一个 \(p\) 用来取模。但是有可能存在取模后数字一样的情况,为了使碰撞的概率尽可能小, \(p\) 必须是奇数,尽量为质数,而且要增大,这里选用 \(10^9+7\)

双模哈希法
就是要模两次,不常用,略。

自然溢出法(不模哈希法)
让他自己爆掉 unsigned long long,让其自然取模,时间复杂度很低。
所以应该用自然溢出法。
时间排序:双模>单模>不模
哈希碰撞率:不模>单模>双模