ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021牛客暑期多校训练营10 A - Browser Games

2021-09-07 21:04:06  阅读:163  来源: 互联网

标签:10 前缀 map 位置 多校 牛客 字符串 pair define


思路:
显然对于位置\(i\)我们要考虑的是\(i+1...n\)的限制,所以我们倒序考虑,对于第\(n\)个串,它的答案不受其他串影响,所以就是前\(n\)个串首字符的种类数即可,这样最优的包含所有字符串的至少长度为\(1\)的前缀。

假设当前位置为\(i\),我们要考虑的是当前的这个串\(s_i\)的每个前缀会对其他的字符串的答案产生怎样的影响。
我们用一个标记数组记录一下对于任意一个数组使得前缀不与\(s_{i}...s_n\)任意一个字符串的任意一个前缀相等的位置。
遍历\(s_i\)的每个前缀,假如其他串的当前位置与这个前缀相等,那么那个串就必定不能取这个前缀否则就会使得题目说的未开启的比赛发生泄漏,所以就是每次用\(s_i\)的每个前缀去更新\(map\),同时把这些相同的值删除掉表示不能使用。
每次操作完,当前\(map\)的大小即为答案,因为是从最后一个字符串的最优值更新过来的,所以当前也一定时满足题意的最好答案。

快速查询相同前缀用\(map+hash\)完成。

这道题,\(map\)会超时,建议使用\(unordered\_map/hash\_map\)。
unordered_map详解

#include <bits/stdc++.h>
#include <ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

#define pb push_back
#define eb emplace_back
#define MP make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lson rt<<1
#define rson rt<<1|1
#define CLOSE std::ios::sync_with_stdio(false)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-6;
const int N = 1e5 + 10;

struct Hash {//一个用结构体封装的hash双模数哈希
	int x,y,MOD1 = 1000000007,MOD2 = 1000000009;
	Hash(){}
	Hash(int _x,int _y) { x = _x; y = _y; }
	Hash operator + (const Hash &a) const {
		return Hash((x + a.x) % MOD1,(y + a.y) % MOD2);
	}	
	Hash operator - (const Hash &a) const {
		return Hash((x - a.x + MOD1) % MOD1,(y - a.y + MOD2) % MOD2);
	}
	Hash operator * (const Hash &a) const {
		return Hash(1ll * x * a.x % MOD1,1ll * y * a.y % MOD2);
	}
	ll val() {
		return 1ll * x * MOD2 + y;
	}
}base(131,13331),hs[N];

int n,cur_pos[N],ans[N];//记录每个串当前去当前位置的前缀能使得字符串都是合法的前缀串
char s[N][110],len[N];
std::unordered_map<ll,vector<int> >mp;//存放每个哈希值在哪些位置出现过
//普通map超时

void solve() {
	scanf("%d",&n);
	for(int i = 1;i <= n;i ++) {
		scanf("%s",s[i]+1);
		len[i] = strlen(s[i]+1);
		hs[i] = Hash(s[i][1]-'a'+1,s[i][1]-'a'+1);
		mp[hs[i].val()].pb(i);
		cur_pos[i] = 1;
	}
	for(int i = n;i >= 1;i --) {
		ans[i] = sz(mp);
		Hash tmp(0,0);
		for(int j = 1;j <= len[i];j ++) {
			tmp = tmp * base + Hash(s[i][j]-'a'+1,s[i][j]-'a'+1);
			auto it = mp.find(tmp.val());
			if(it == mp.end()) continue;
			for(auto k : it->second) {
				// cout << k << "***\n";
				if(k == i) continue;                    
				cur_pos[k]++;                  
				hs[k] = hs[k] * base + Hash(s[k][cur_pos[k]]-'a'+1,s[k][cur_pos[k]]-'a'+1);//更新对于每个数可用合法的前缀
				mp[hs[k].val()].pb(k);
			}
			mp.erase(tmp.val());//当前的这个前缀已经不能用了
			// }
		}
	}
	// for(int i = 1;i <= n;i ++) printf("%d : %d\n",i,cur_pos[i]);
	for(int i = 1;i <= n;i ++) {
		printf("%d\n",ans[i]);
	}
}

int main() {
	solve();
	return 0;
}

标签:10,前缀,map,位置,多校,牛客,字符串,pair,define
来源: https://www.cnblogs.com/forward77/p/15240107.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有