首页 > 其他分享 >CF1200E Compress Words 字符串哈希/双重哈希

CF1200E Compress Words 字符串哈希/双重哈希

时间:2023-04-04 23:24:03浏览次数:45  
标签:CF1200E 哈希 int hs Words 字符串 string 答案

题目地址

题意:给你若干个字符串,答案串初始为空。第i 步将第 i 个字符串加到答案串的后面,但是尽量地去掉重复部分(即去掉一个最长的、是原答案串的后缀、也是第 i 个串的前缀的字符串),求最后得到的字符串。

Solution

字符串哈希练习题,做完之后对哈希的理解更深刻了

因为求原字符串的后缀和第i个串的前缀,所以我们可以边记录第i个串的哈希值,边与原字符串进行比较

处理到第i个串的第j位时,如果j比原字符串长度大,可以直接退出

之后边给答案加入第i个串的字符,边处理答案串的哈希值

这里用了一个双hash的方法,从而减少出错率

求区间子串的哈希值

int get_hash(int l,int r,int k)
{
	return ((hs_s[r][k]-hs_s[l-1][k]*p[r-l+1][k])%m[k]+m[k])%m[k];
}

AC代码:

int b[2]={171,2333333};
int m[2]={1000000007,999999998};
int p[N][2];
int hs_s[N][2];
int hs_t[N][2];

char s[N];
string t;

void init()
{
	p[0][0]=p[0][1]=1;
	for(int i=1;i<N-3;i++)
	{
		p[i][0]=(p[i-1][0]*b[0])%m[0];
		p[i][1]=(p[i-1][1]*b[1])%m[1];
	}
}

int get_hash(int l,int r,int k)
{
	return ((hs_s[r][k]-hs_s[l-1][k]*p[r-l+1][k])%m[k]+m[k])%m[k];
}



void solve()
{
	init();
	int n;cin>>n;
	string x;
	cin>>x;
	int len=x.length();
	hs_s[0][0]=hs_s[0][1]=0;
	for(int i=1;i<=len;i++)
	{
		s[i]=x[i-1];
		for(int k=0;k<2;k++)
		{
			hs_s[i][k]=(hs_s[i-1][k]*b[k]+x[i-1])%m[k];
		}
	}
	
	for(int i=2;i<=n;i++)
	{
		cin>>t;
		hs_t[0][0]=hs_t[0][1]=0;
		int pos=1;
		int flag=1;
		for(int j=1;j<=t.length()&&len-j+1>0;j++)
		{
			flag=1;
			for(int k=0;k<2;k++)
			{
				hs_t[j][k]=(t[j-1]+hs_t[j-1][k]*b[k])%m[k];
				if(hs_t[j][k]!=get_hash(len-j+1,len,k))flag=0;
				/*cout<<hs_t[j][k]<<"\n";
				cout<<len-j+1<<" "<<len<<":"<<get_hash(len-j+1,len,k)<<"\n";*/
			}
			
			if(flag)pos=j+1;
		}
		
		for(int j=pos;j<=t.length();j++)
		{
			s[++len]=t[j-1];
			for(int k=0;k<2;k++)
			{
				hs_s[len][k]=(hs_s[len-1][k]*b[k]+s[len])%m[k];
			}
			
		}
		/*cout<<pos<<"\n";
		for(int i=1;i<=len;i++)cout<<s[i];
		cout<<"\n";*/
	}
	for(int i=1;i<=len;i++)cout<<s[i];
	cout<<"\n";
}

标签:CF1200E,哈希,int,hs,Words,字符串,string,答案
From: https://www.cnblogs.com/HikariFears/p/17288235.html

相关文章

  • hash哈希表
    当我们想在内存中通过关键字寻找特定数据时(键值对),总是希望能快速找到所需数据,在无索引的情况使用二分查找、二叉树、b数也只能在O(lgn)的时间复杂度上查找。而通过对数据的关键字和其存储位置建立对应关系f,使得每个关键字通过f能唯一确定一个储存位置,那么就能通过对关键字的查......
  • 最小覆盖子串(哈希表、字符串)、两数之和(数组、哈希表)、二叉树的层序遍历 II(树、广
    最小覆盖子串(哈希表、字符串)给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串,则返回空字符串""。**注意:**如果s中存在这样的子串,我们保证它是唯一的答案。示例1:输入:s="ADOBECODEBANC",t="ABC"输出:"B......
  • 内网渗透之哈希传递攻击
    (作业记录0x01利用VMware的克隆功能克隆一台win7,取名为win7-2。0x02启用win7和win7-2的系统管理员Administrator账户及设置密码法一启用管理员账号administrator设置密码为123456法二打开开始菜单,右击“计算机”,选择“管理”。在“计算机管理”窗口,依次定位到“本......
  • 有关哈希表简单的散列函数实现-Java实现
    其实现不难,所以直接贴代码:1packagedataSrtuct;23importjava.util.ArrayList;4importjava.util.LinkedList;56publicclassHashTab{7publicstaticvoidmain(String[]args){8hashTablehashT=newhashTable(10);9......
  • 由入门题回想起来的哈希表
    洛谷P2550P2550[AHOI2001]彩票摇奖-洛谷|计算机科学教育新生态(luogu.com.cn)可以看到这是个入门题,完全可以用暴力查找(for循环二重嵌套)来实现,但是这个查找形式让我想起了一个月之前学的哈希表(HashMap)众所周知,利用哈希表可以将查找的时间复杂度优化到O(1)的水平,而且本题需......
  • 四数相加|哈希表
    四数相加给定四个数组,如果四个数相加,如果和为0那么计数加一,最后输出一共有几个组合使得和为0。这题应用哈希表解决对应题目454.四数相加II哈希表使用哈希表,保存前两个数组对应的组合之和。value为两数相之和,如果有相同那么value加一。之和再遍历剩下两个数组之和的组合,再......
  • 环形链表|哈希、快慢指针
    环形链表判断一个链表中是否有环,如果有返回环的起始位置。难点有两个,一是判断是否有环,二是找到起始点。这里有两种方法,一种是哈希集,另一种是快慢指针。对应题目142.环......
  • 两数组的交集|哈希集
    两个数组的交集寻找两个数组相同的元素,注意返回元素的唯一性对应题目349.两个数组的交集哈希集合使用两个哈希集合,第一个保存前一个数组的元素,第二个集合遍历第二个......
  • Java数据结构 HashMap 哈希表定义使用
    1.HashMapHashMap是一个散列表,它存储的内容是键值(key-value)映射。其中key和value类型可以相同也就而已不同,根据定义。2.HashMap使用1)定义HashMap<Integer,String>hashmap1......
  • Redis 哈希(Hash)
    Redis哈希(Hash)Redishash是一个string类型的field(字段)和value(值)的映射表,hash特别适合用于存储对象。Redis中每个hash可以存储232-1键值对(40多亿)。实......