// // // // // // // // // // // // // //

关于字符串哈希

字符串哈希

前言

让我懒死算了

1. 子串查找

/*
  Time: 1.6
  Worker: Blank_space
  Source: #103. 子串查找
*/
/*--------------------------------------------*/
#include<cstdio>
#include<string>
#include<iostream>
#define int signed long long
using namespace std;
/*--------------------------------------头文件*/
const int base = 53;
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
string s1, s2;
int _s1, _s2, p1[C], p2[C], hash1[C], hash2[C], ans;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/

/*----------------------------------------函数*/
signed main()
{
//  freopen("1.in","r",stdin);
//  freopen(".out","w",stdout);

	cin >> s1 >> s2; p1[0] = p2[0] = 1;
	int n = s1.length() - 1, m = s2.length() - 1;
	for(int i = 1; i <= 1e6; i++) p1[i] = p1[i - 1] * base % mod1, p2[i] = p2[i - 1] * base % mod2;
    for(int i = 0; i <= m; i++) _s1 = (_s1 * base % mod1 + s2[i] -  64) % mod1, _s2 = (_s2 * base % mod2 + s2[i] - 64) % mod2;
    for(int i = 0; i <= n; i++) hash1[i] = (hash1[i - 1] * base % mod1 + s1[i] - 64) % mod1, hash2[i] = (hash2[i - 1] * base % mod2 + s1[i] - 64) % mod2;
    for(int i = m; i <= n; i++)
		if(_s1 == ((hash1[i] - hash1[i - m - 1] * p1[m + 1] % mod1) + mod1) % mod1 && _s2 == ((hash2[i] - hash2[i - m - 1] * p2[m + 1] % mod2) + mod2) % mod2) ans++;
    printf("%lld", ans);
    
//  fclose(stdin);
//  fclose(stdout);
	return 0;
}

2. 图书管理

/*
  Time: 1.6
  Worker: Blank_space
  Source: #10034. 「一本通 2.1 例 2」图书管理
*/
/*---------------------------------------------------*/
#include<cstdio>
#include<string.h>
#include<iostream>
#define ll long long
using namespace std;
/*---------------------------------------------------*/
const int base = 1e3;
const int A = 1e4 + 7;
const int B = 1e5 + 9;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod1 = 1e7 + 7;
const int mod2 = 1e7 + 9;
const int INF = 0x3f3f3f3f;
/*---------------------------------------------------*/
int n, p1[250], p2[250];
char opt[5], ss[250];
bool vis1[D], vis2[D];
/*---------------------------------------------------*/
int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*---------------------------------------------------*/
int main()
{
//	freopen("", "r", stdin);
//	freopen("", "w", stdout);
	
	n = read();
	for(int i = 1; i <= 210; i++) p1[i] = p1[i - 1] * base % mod1, p2[i] = p2[i - 1] * base % mod2;
	for(int i = 1; i <= n; i++)
	{
		cin >> opt; ll t1 = 1, t2 = 1; gets(ss);
		for(int j = 0; j <= strlen(ss) - 1; j++) t1 = (t1 * base % mod1 + ss[j]) % mod1, t2 = (t2 * base % mod2 + ss[j]) % mod2;
		if(opt[0] == 'a') vis1[t1] = 1, vis2[t2] = 1;
		if(opt[0] == 'f')
			if(vis1[t1] && vis2[t2]) puts("yes");
			else puts("no");
	}
	
//	fclose(stdin);
//	fclose(stdout);
}

3. Power Strings

/*
  Time: 1.6
  Worker: Blank_space
  Source: #10035. 「一本通 2.1 练习 1」Power Strings
  直接从一开始截取 判断是否满足
  不需要从中间截取 因为如果能从中间截取到满足条件的 则必定也能拼成前面的
  而一定是前面的先被选到 
*/
/*---------------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
/*---------------------------------------------------*/
const int base = 233;
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*---------------------------------------------------*/
char s[C];
int t, len;
ll h[C], p[C];
/*---------------------------------------------------*/
int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
bool check(int x)
{
//	printf("\n%lld\n", h[x]);
	for(int i = 0; i < len; i += x)	if(h[x] != (h[i + x] - h[i] * p[x] % mod + mod) % mod) return 0;
	return 1;
}
/*---------------------------------------------------*/
int main()
{
//	freopen("", "r", stdin);
//	freopen("", "w", stdout);
	
	p[0] = 1;
	for(int i = 1; i <= 1e6; i++) p[i] = p[i - 1] * base % mod;
	while(1)
	{
		cin >> (s + 1); if(s[1] == '.') return 0;
		len = strlen(s + 1);
		for(int i = 1; i <= len; i++)
			h[i] = (h[i - 1] * base % mod + s[i]) % mod;
		for(int i = 1; i <= len; i++)
		{
			if(len % i) continue;
			if(check(i)) {printf("%d\n", len / i); break;}
		}
	}
	
//	fclose(stdin);
//	fclose(stdout);
}

4. Seek the Name, Seek the Fame

/*
  Time: 1.9
  Worker: Blank_space
  Source: #10036. 「一本通 2.1 练习 2」Seek the Name, Seek the Fame
*/
/*---------------------------------------------------*/
#include<cstdio>
#include<cstring>
#define ll long long
#define emm(x) memset(x, 0, sizeof x)
using namespace std;
/*---------------------------------------------------*/
const int base = 60;
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
const int INF = 0x3f3f3f3f;
/*---------------------------------------------------*/
ll h1[B << 2], h2[B << 2], pow1[B << 2], pow2[B << 2];
char s[B << 2];
/*---------------------------------------------------*/
int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*---------------------------------------------------*/
int main()
{
//	freopen("", "r", stdin);
//	freopen("", "w", stdout);
	
	pow1[0] = 1; pow2[0] = 1;
	for(int i = 1; i <= 4e5; i++) pow1[i] = pow1[i - 1] * base % mod1, pow2[i] = pow2[i - 1] * base % mod2;
	while(scanf("%s", s + 1) != EOF)
	{
		int len = strlen(s + 1); emm(h1); emm(h2); 
		for(int i = 1; i <= len; i++) h1[i] = (h1[i - 1] * base % mod1 + s[i] - 96 + mod1) % mod1,
									  h2[i] = (h2[i - 1] * base % mod2 + s[i] - 96 + mod2) % mod2;
		for(int i = 1; i <= len; i++)
			if(h1[i] == (h1[len] - h1[len - i] * pow1[i] % mod1 + mod1) % mod1 &&
			   h2[i] == (h2[len] - h2[len - i] * pow2[i] % mod2 + mod2) % mod2) printf("%d ", i);
		puts("");
	}
	
//	fclose(stdin);
//	fclose(stdout);
}

5. Three Friends

/*
  Time: 1.10
  Worker: Blank_space
  Source: #2823. 「BalticOI 2014 Day 1」三个朋友
  枚举删除每一个字符 对剩余的字符进行哈希值拼接 
  锅掉了
  题目中没有提到的是 只有删除后的字符串不同时才视为两种不同的情况
  上 map 
  所以我样例挂了
  微调  哈希值的拼接写反 
*/
/*---------------------------------------------------*/
#include<map>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
/*---------------------------------------------------*/
const int base = 70;
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*---------------------------------------------------*/
ll n, t, h[C << 1], pow[C << 1], k;
bool _p;
char s[C << 1];
map <ll, int> sum;
/*---------------------------------------------------*/
int read()
{
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
bool check1(int x)
{
//	if(x == n && h[t] == (h[n - 1] - h[t] * pow[t] % mod + mod) % mod) return 1;
//	int _t = x <= t ? t + 1 : t; int y = x > t ? n - x + 1 : x;
	if(h[x - 1] != (h[t + x] - h[t + 1] * pow[x - 1] % mod + mod) % mod) return 0;
	if((h[t + 1] - h[x] * pow[t + 1 - x] % mod + mod) % mod != (h[n] - h[t + x] * pow[t + 1 - x] % mod + mod) % mod) return 0;
	return 1;
}
bool check2(int x)
{
	if((h[n] - h[x] * pow[n - x] % mod + mod) % mod != (h[t] - h[x - t - 1] * pow[n - x] % mod + mod) % mod) return 0;
	if(h[t + x - n] != (h[x - 1] - h[t] * pow[x - t - 1] % mod + mod) % mod) return 0;
	return 1;
}
void print1()
{
	for(int i = 1; i < k; i++) printf("%c", s[i]);
	for(int i = k + 1; i <= t + 1; i++) printf("%c", s[i]);
}
void print2()
{
	for(int i = 1; i <= t; i++) printf("%c", s[i]);
}
/*---------------------------------------------------*/
int main()
{
//	freopen("", "r", stdin);
//	freopen("", "w", stdout);
	
	n = read();
	if(!(n & 1)) {puts("NOT POSSIBLE"); return 0;}
	scanf("%s", s + 1);
	int len = strlen(s + 1); t = n >> 1; pow[0] = 1;
	for(int i = 1; i <= len; i++) h[i] = (h[i - 1] * base % mod + s[i] - 64) % mod, pow[i] = pow[i - 1] * base % mod;
	for(int i = 1; i <= len; i++)
	{
		bool p = i <= t ? check1(i) : check2(i);
		if(!p) continue;
		long long d = ((h[n] - h[i] * pow[n - i] % mod + mod) % mod + h[i - 1] * pow[n - i] % mod) % mod;
		if(_p && !sum[d]) {puts("NOT UNIQUE"); return 0;}
		sum[d]++; k = i; _p = 1;
	}
	if(_p) k <= t ? print1() : print2();
	else puts("NOT POSSIBLE");
	
//	fclose(stdin);
//	fclose(stdout);
}

6. A Horrible Poem

详见题解:A Horrible Poem


其他的题目没有时间做了...
等以后找机会补上 虽然这个以后可能会很远就是了

posted @ 2021-01-30 11:52  Blank_space  阅读(35)  评论(0编辑  收藏  举报
// // // // // // //