题目链接【https://www.oj.swust.edu.cn/problem/show/2610】
题意:给你一个字符串,让你判断这个字符串是不是回文串,字符串的长度是1<len<1e7,内存是4096KB。
题解:首先这1e7个字符是存不下的,1e71024=9765KB>4096kB。那么怎么办?字符串哈希,先对字符串的前半部分进行哈希,然后在对字符串后半部分进行哈希,如果两部分的哈希值相同,那么这个字符串就是回文串。
BKDRH哈希,哈希公式为has=has*seed+s[i],seed为31,131,1313,这里选择131。对于后半部分has+=pow(seed,i-1)*s[i]。但是这样哈希会有漏洞,需要更近一步的完善,我们用unsigned long long 存HAS值,所以他会自动取模(2^64-1),
对于前半部分我们维护两个HAS值,分别对两个不同的素数取模,后半部分也一样。那么我们就维护这两对哈希值,只有当这两对哈希值都分别相等的时候,我们才认为这两段字符串是相等的,也就是回文串。具体看代码。
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ULL; const ULL modA = 1e9 + 7; const ULL modB = 1e9 + 9; ULL has[5], SEED = 131; int N; int main () { while(~scanf("%d", &N)) { has[0] = has[1] = 0; has[2] = has[3] = 0; char s; char S[5]; gets(S); for(int i = 1; i <= N / 2; i++) { s = getchar(); ULL t = (ULL)s; has[0] = (has[0] * SEED + t) % modA; has[1] = (has[1] * SEED + t) % modB; } if(N % 2) s = getchar(); ULL seed[3]; seed[0] = seed[1] = seed[2] = (ULL)1; for(int i = 1; i <= N / 2; i++) { s = getchar(); ULL t = (ULL)s ; has[2] = (has[2] + t * seed[0]) % modA; has[3] = (has[3] + t * seed[1]) % modB; seed[0] = seed[0] * SEED % modA; seed[1] = seed[1] * SEED % modB; } if(has[0] == has[2] && has[1] == has[3] ) printf("YES "); else printf("NO "); } return 0; }