如果不懂什么是字符串哈希,那么你可以看yxc大佬的视频
算法竞赛进阶指南1.4-1.5哈希与字符串
题目:兔子与兔子
代码:
#include
using namespace std;
const int maxn = 1000100;
#define ULL unsigned long long
ULL h[maxn], p[maxn];
char str[maxn];
int main(){
scanf("%s", str+1);
int n = strlen(str+1), q;
scanf("%d", &q);
p[0] = 1;
for(int i = 1; i <= n; i++){
h[i] = h[i-1] * 131+(str[i] - 'a' + 1);
p[i] = p[i-1] * 131;
}
for(int i = 1; i <= q; i++){
int l_1, r_1, l_2, r_2;
scanf("%d %d %d %d", &l_1, &r_1, & l_2, &r_2);
if(h[r_1]-h[l_1-1]*p[r_1-l_1+1] == h[r_2]-h[l_2-1]*p[r_2-l_2+1]){
printf("Yes\n");
}
else {
printf("No\n");
}
}
return 0;
}
题目:回文子串的最大长度
题意:给你一个字符串,问你这个字符串最大的回文串是多长?
题解:字符串哈希+二分查找
代码:
#include
using namespace std;
const int maxn = 2001000;//注意数组开的范围
typedef unsigned long long ULL;
char s[maxn];
ULL hr[maxn], hl[maxn], p[maxn];
int base = 131;
ULL query(ULL h[], int l, int r)
{
return h[r] - h[l-1]*p[r-l+1];
}
int main()
{
int ca = 0;
while(scanf("%s", s+1) && strcmp(s+1, "END"))
{
int n = strlen(s+1);
n *= 2;
for(int i = n; i > 0; i -= 2) //强行在数组中加入新的辅助符号
{
s[i] = s[i/2];
s[i-1] = 'z'+1;
}
p[0] = 1;
for(int i = 1, j = n; i <= n; i++, j--) //字符串哈希
{
hl[i] = hl[i-1]*base + (s[i]-'a'+1);
hr[i] = hr[i-1]*base +(s[j]-'a'+1);
p[i] = p[i-1]*base;
}
int res = 0;
int l, r;
for(int i = 1; i <= n; i++)
{
l = 0, r = min(i-1, n-i);
while(l < r)
{
int mid = (l+r+1)>>1;
if(query(hl, i-mid, i-1) != query(hr, n-(i+mid)+1, n-(i+1)+1))r = mid-1;
else l = mid;
}
if(s[i-l] <= 'z')res = max(res, l+1);
else res = max(res, l);
}
printf("Case %d: %d\n", ++ca, res);
}
return 0;
}
思想:字符串哈希+二分查找
代码:
#include
using namespace std;
const int maxn = 301000;
typedef unsigned long long ULL;
ULL p[maxn], h[maxn];
char s[maxn];
int vis[maxn], base = 131, n;
ULL get(int l, int r){
return h[r] - h[l-1]*p[r-l+1];
}
int Binary_Search(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 l = Binary_Search(a, b);
int a_val = a+l > n ? INT_MIN : s[a+l];
int b_val = b+l > n ? INT_MIN : s[b+l];
return a_val < b_val;
}
int main(){
scanf("%s", s+1);
n = strlen(s+1);
p[0] = 1;
for(int i = 1; i <= n; i++){
h[i] = h[i-1]*base+(s[i]-'a'+1);
p[i] = p[i-1]*base;
vis[i] = i;
}
sort(vis+1, vis+1+n, cmp);
for(int i = 1; i <= n; i++){
printf("%d ", vis[i]-1);
}
cout<