「BalticOI 2014 Day 1」三个朋友(进制hash)

该博客主要讨论如何通过字符串的复制和插入操作,重新构造原始字符串。文章介绍了使用进制Hash模板解决此问题的方法,包括计算子串的Hash值,并通过枚举插入位置来判断字符串的可行性与唯一性。此外,还提供了相关的代码实现和样例分析。
摘要由CSDN通过智能技术生成

题目链接:https://loj.ac/problem/2823

描述:

给定一个字符串S ,先将字符串 S 复制一次(变成双倍快乐),得到字符串 T,然后在U中插入一个字符,得到字符串U 。

给出字符串U ,重新构造出字符串 S。

所有字符串只包含大写英文字母。

输入格式

第一行一个整数 ,表示字符串 U 的长度。

第二行一个长度为 n 的字符串,表示字符串U 。

输出格式

一行一个字符串S,表示字符串 。

特别地:

  • 如果字符串无法按照上述方法构造出来,输出 NOT POSSIBLE
  • 如果字符串  不唯一,输出 NOT UNIQUE

样例

样例输入 1

7
ABXCABC

样例输出 1

ABC

样例输入 2

6
ABCDEF

样例输出 2

NOT POSSIBLE

样例输入 3

9
ABABABABA

样例输出 3

NOT UNIQUE

分析:进制hash模板,枚举被添加的是哪一位,用hash判断两段是否相等,注意not unique是不同的串s,不是所插字符的位置不同。

[l,r]的hash值
ll get(int l,int r){
	return (h[r]-h[l-1]*p[r-l+1]%md1+md1)%md1;
}

[l,r]删去x的hash值
ll query(int l,int r,int x){
	return (get(l,x-1)*p[r-x]%md1+get(x+1,r))%md1;
}

hash更多应用:

作者:henry_y

链接:https://blog.nowcoder.net/n/39e7cbeeec014e63800a553fdc1e4e5c

来源:牛客网

 

#include<bits/stdc++.h>
#define N 1000010
#define ll long long
using namespace std;
char s[N*2];
ll h[N*2],p[N*2];
const int md1=1e9+7,md2=1e9+9,base=2333;
ll get(int l,int r){
	if(l>r)return 0;
	return (h[r]-h[l-1]*p[r-l+1]%md1+md1)%md1;
}
ll query(int l,int r,int x){
	return (get(l,x-1)*p[r-x]%md1+get(x+1,r))%md1;
}
int n;
map<ll,int>ma;
int main(){
	scanf("%d",&n);
	scanf("%s",s+1);
	if(n%2==0){
		printf("NOT POSSIBLE");return 0;
	}
	p[0]=1;h[0]=0;
	for(int i=1;i<=n;i++)h[i]=(h[i-1]*base%md1+s[i])%md1,p[i]=p[i-1]*base%md1;
	int ans=0,id;
	for(int i=1;i<=n;i++){
		if(i<=n/2+1&&query(1,n/2+1,i)==get(n/2+2,n)){
			if(!ma.count(get(n/2+2,n))){
				ans++;id=i;ma[get(n/2+2,n)]=1;
			}
		}
		if(i>n/2+1&&get(1,n/2)==query(n/2+1,n,i)){
			if(!ma.count(get(1,n/2))){
				ans++;id=i;ma[get(1,n/2)]=1;
			}
		}
	}
	if(ans==0)printf("NOT POSSIBLE");
	else if(ans==1){
		int t=0;
		for(int i=1;i<=n;i++){
			if(i!=id&&t<n/2)printf("%c",s[i]),t++;
		}
	}
	else printf("NOT UNIQUE");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值