前言

字符串哈希,非常非常好用NB的方法,虽然有一定概率会翻车(翻车概率极低),但是这个是真的NB,你如果会这个在大多数场合可以避免掉有一些算法的学习,比如马拉车算法,
你学马拉车只能处理回文字符串,虽然马拉车是O(N) ,但在非极端测试点的情况下我们可以用字符串哈希来偷鸡,字符串哈希简单好用,比KMP简单很多。(KMP有不可替代的场合,KMP还是有必要的)字符串哈希能处理非常非常多的情况,话不多说来道经典的题:

字符串哈希

给定一个长度为n的字符串,再给定m个询问,每个询问包含四个整数l1,r1,l2,r2,请你判断[l1,r1]和[l2,r2]这两个区间所包含的字符串子串是否完全相同。

字符串中只包含大小写英文字母和数字。

输入格式
第一行包含整数n和m,表示字符串长度和询问次数。

第二行包含一个长度为n的字符串,字符串中只包含大小写英文字母和数字。

接下来m行,每行包含四个整数l1,r1,l2,r2,表示一次询问所涉及的两个区间。

注意,字符串的位置从1开始编号。

输出格式
对于每个询问输出一个结果,如果两个字符串子串完全相同则输出“Yes”,否则输出“No”。

每个结果占一行。

#include<iostream>
#include<algorithm>
#include<cstring>#define ull unsigned long longusing namespace std;const int N=100010,base=131;char str[N];
ull p[N],h[N];
int n,m;int get(int l,int r)
{return h[r]-h[l-1]*p[r-l+1];
}
int main(){//freopen("data.in","r",stdin);//freopen("data.out","w",stdout);scanf("%d%d",&n,&m);scanf("%s",str+1);p[0]=1;for(int i=1;i<=n;i++){p[i]=p[i-1]*base;h[i]=h[i-1]*base+str[i]-'a'+1;}while(m--){int l1,l2,r1,r2;cin>>l1>>r1>>l2>>r2;if(get(l1,r1)!=get(l2,r2)) puts("No");else puts("Yes");}return 0;
}

原理就是用131进制来表示一个字符串(131不容易翻车),原理非常简单,蒟蒻我笔拙主要是懒 ,如果想听更好的讲解请移步至ACwing。还有就是为了保证代码查询速度为O(1)将131n保存下来.

回文子串的最大长度

如果一个字符串正着读和倒着读是一样的,则称它是回文的。

给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。

输入格式
输入将包含最多30个测试用例,每个测试用例占一行,以最多1000000个小写字符的形式给出。

输入以一个以字符串“END”(不包括引号)开头的行表示输入终止。

输出格式
对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。

每个输出占一行。

这是经典的马拉车的题目(数据量很恐怖,但O(nlogn)不至于炸),但如果我们会字符串哈希一样可以偷鸡。

#include<iostream>
#include<algorithm>
#include<cstring>#define ull unsigned long longusing namespace std;const int N=2000010,base=131;ull p[N],hl[N],hr[N];
char str[N];ull get(ull h[],int l,int r)
{return h[r]-h[l-1]*p[r-l+1];
}
int main(){int T=0;while(scanf("%s",str+1),strcmp(str+1,"END")){int n=strlen(str+1);for(int i=2*n;i;i-=2){str[i]=str[i/2];str[i-1]='z'+1;}n*=2;p[0]=1;for(int i=1,j=n;i<=n;i++,j--){p[i]=p[i-1]*base;hl[i]=hl[i-1]*base+str[i]-'a'+1;hr[i]=hr[i-1]*base+str[j]-'a'+1;}int res=0;for(int i=1;i<=n;i++){int l=0,r=min(i-1,n-i);while(l<r){int mid=l+r+1>>1;if(get(hl,i-mid,i-1)!=get(hr,n-(i+mid)+1,n-(i+1)+1)) r=mid-1;else l=mid;}if(str[i-l]<='z')res=max(res,l+1);else res=max(res,l);}printf("Case %d: %d\n",++T,res);}return 0;
}

可以看见代码非常的简洁,我们防止字符串出现偶数,用插孔法把他变成奇数。
然后以所有点为中点二分枚举半径。代码非常的简单,没什么好说的。

后缀数组

后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围。

在本题中,我们希望使用快排、Hash与二分实现一个简单的O(nlog2n)的后缀数组求法。

详细地说,给定一个长度为 n 的字符串S(下标 0~n-1),我们可以用整数 k(0≤k<n) 表示字符串S的后缀 S(k~n-1)。

把字符串S的所有后缀按照字典序排列,排名为 i 的后缀记为 SA[i]。

额外地,我们考虑排名为 i 的后缀与排名为 i-1 的后缀,把二者的最长公共前缀的长度记为 Height[i]。

我们的任务就是求出SA与Height这两个数组。

输入格式
输入一个字符串,其长度不超过30万。

输出格式
第一行为数组SA,相邻两个整数用1个空格隔开。

第二行为数组Height,相邻两个整数用1个空格隔开,我们规定Height[1]=0。

后缀数组,很多被这个题目的名字给吓到了,我没学过后缀数组怎么办,没关系,我也不会 我们可以用字符串哈希偷鸡,先看代码。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<limits.h>#define ull unsigned long longusing namespace std;const int N=300010,base=131;char str[N];
ull h[N],p[N];
int n,sa[N];ull get(int l,int r)
{return h[r]-h[l-1]*p[r-l+1];
}int get_common_pre(int a,int b)
{int l=0,r=min(n-a+1,n-b+1);while(l<r){int mid=l+r+1>>1;if(get(a,a+mid-1)!=get(b,b+mid-1)) r=mid-1;else l=mid;}return l;
}
bool CMP(int a,int b)
{int len=get_common_pre(a,b);int ra=a+len>n?INT_MIN:str[a+len];int rb=b+len>n?INT_MIN:str[b+len];return ra<rb;
}
int main(){scanf("%s",str+1);n=strlen(str+1);p[0]=1;for(int i=1;i<=n;i++){p[i]=p[i-1]*base;h[i]=h[i-1]*base+str[i]-'a'+1;sa[i]=i;}sort(sa+1,sa+n+1,CMP);for(int i=1;i<=n;i++) printf("%d ",sa[i]-1);puts("");for(int i=1;i<=n;i++){if(i==1) printf("0 ");else printf("%d ",get_common_pre(sa[i],sa[i-1]));}puts("");return 0;
}

我们利用字符串哈希+快排+二分完成偷鸡。
假设字符串"ponoiiipoi" n=10
后缀数组的意思就是:

i str
10 i
9 oi
8 poi
7 ipoi
6 iipoi
5 iiipoi
4 oiiipoi
3 noiiipoi
2 onoiiipoi
1 ponoiiipoi

我们利用字符串哈希的特点用二分法求得两个后缀数组的最长公共前缀,然后完成CMP函数,快排就得到了答案,代码非常的简洁,这样就避免了那些,我们看不懂的高级算法了。~ 。~

字符串处理之---字符串哈希相关推荐

  1. LeetCode 1684. 统计一致字符串的数目(哈希)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个由不同字符组成的字符串 allowed 和一个字符串数组 words . 如果一个字符串的每一个字符都在 allowed 中,就称这个字符串是 一 ...

  2. 字符串留用与字符串池

    1.关于字符串操作对应用程序性能的影响 字符串相等性检查是应用程序常见的操作,于此同时,这也是一种严重损害性能的操作.执行序号(字符串的二进制)相等行检查时,CLR会进行以下操作: 1.判断字符串的长 ...

  3. 一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对

    一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对,如abc和cba. 当时怎么想的忘记了,现在重新思考一下,文件的大小上限是10G,不可能在内存操作了.考虑设计一种hash使 ...

  4. java 字符串函数_Java字符串函数– 25+必须知道方法

    java 字符串函数 Java字符串函数 (Java String Functions) Java String class has a lot of functions to manipulate ...

  5. python 字符串函数_Python字符串函数

    python 字符串函数 Python provides a lot of built-in functions to manipulate strings. Python String is imm ...

  6. java 字符串面试_Java字符串面试问答

    java 字符串面试 String is one of the most widely used Java Class. Here I am listing some important Java S ...

  7. groovy if 判断字符串_Groovy(二)-字符串

    文本是由一连串的字符也就是字符串组成,Groovy让你实例化java.lang.String实体,和其他编程语言中的内插字符串GStrings (groovy.lang.GString)一样. 单引号 ...

  8. Go 学习笔记(51)— Go 标准库之 strings(字符串比较、字符串前后缀、字符串统计、字符串索引、字符串包含、字符串转换、字符串复制、字符串替换、字符串去除、字符串分割和连接)

    1. 概述说明 import "strings" strings 包实现了用于操作字符的简单函数. strings 包与 bytes 包中的函数用法基本一样. 2. 主要函数 2. ...

  9. python字符串基本形式_python字符串常用方式

    class str(basestring): """ str(object='') -> string Return a nice string represent ...

  10. Java案例——统计字符串中每个字符串出现的次数

    统计字符串中每个字符串出现的次数 需求: 1.键盘录入一个字符串,要求统计字符串中每个字符串出现的次数 举例:键盘录入"aababcabcdabcde" 在控制台输出:" ...

最新文章

  1. parseInt 与 parseFloat 解析
  2. shell截取字符串方法
  3. php全局变量的关键字,PHP变量作用域(全局变量局部变量)globalstatic关键字用法实例分析...
  4. 【技术累积】【点】【编程】【13】XX式编程
  5. sublime配置python运行环境
  6. 耗尽您CPU资源的Explored病毒清除法
  7. WPF-003 popup实现下拉列表的问题
  8. .NET Core MVC扩展实践
  9. mysql卸载权限不够_Linu下启动MySQL结果显示:env: /etc/init.d/mysql:权限不够怎么解决?...
  10. 网易易盾的“外挂对抗战”,游戏出海之路如何走得更安全?
  11. 10.10做题——USACO1.2/洛谷1207回文平方数(Dual Palindromes)
  12. geek软件是干什么的_极客是什么?
  13. 【Linux】Core dump故障分析
  14. [原译]Lambda高手之路第二部分
  15. 和 对比_Yeezy350V2新灰橙真假对比
  16. JSP实用教程(第三版 清华大学出版社)中遇到的问题和解释
  17. 关于CCS软件的Graph功能使用详解
  18. 关于ob函数的使用和应用场景
  19. 转载一篇心灵鸡汤,致在路上奋斗的ACMer
  20. 小米全国高校编程大赛 高弗雷勋爵

热门文章

  1. html5实现圆圈里带一个三角形,Fabric.js - 详细使用教程1(绘制图形:矩形、圆形、三角形、不规则图形)...
  2. 使用Java生成excel文件:apache-poi
  3. 白帽子-高端信息安全培训
  4. C语言实现用指定字符切割字符串并返回数组
  5. 【C语言】问答总结 | 神奇的迭代公式两种解法
  6. 用复利模型创造自己的睡后收入
  7. 剑指Offer:翻转单词顺序 vs 左旋转字符串
  8. python向自己qq邮箱发信息_python使用QQ邮箱发送邮件
  9. 帆软报表在js中修改模板参数
  10. 南邮 OJ 2047 地铁环线