K. Browser Games

K. Browser Games
银川站的K题。第一次写真题,浅浅发个题解记录一下
题目大意:
游戏公司要发布n个游戏,一天发布一个,每个游戏由一个字符串构成,由于游戏公司的一些不当操作。游戏可以通过游戏名前缀进行访问,导致可以利用bug把没发布的游戏全部偷出来,现在老板让你在规划每一天所需要的前缀的最小值,且前i天的前缀不能访问到没发布的游戏
样例:在这里插入图片描述
解释一下样例吧:第一天毫无疑问选u作为前缀可以最小,且不访问到后面的。第二天需要 u hs (为什么不h呢?因为如果以h为前缀就可以访问到第三天的),第三天 只需要 u h(h可以直接访问到2,3的游戏)
思路:
这么多字符串的前缀,考虑Tire树来处理,但首先我们需要算一下内存5万5028*4/1024/1024差不多有300MB,题目给的512MB所以够用 ,首先我们把所有字符串读入然后进行Tire树的初始化。
考虑动态的处理数据,容易想到如果想要前缀数量变小,必须让后面加进来的前缀是前面前缀的前缀(比如说 h 是hs的前缀)这样就可以把前面的前缀给去掉了。但是要注意的地方是,后面要加进来的前缀必须满足后面所有的字符串都没有这个前缀,然后我们把以前的前缀剪掉即可

代码:有一些小注释:


// An highlighted block
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
using namespace std;
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define sz(a) (int) (a).size()
const int N=3*1e6+10;
int son[N][29],cnt[N],idx;
int n,ans;
int bf[N];//记录以前的分支数量
int getnum(char op){
	if(op>='a'&&op<='z') return op-'a';
	else if(op=='.') return 26;
	else return 27;
}
void insert(string s){
	int p=0;
	for(int i=0;s[i];i++){
		int u=getnum(s[i]);
	     if(!son[p][u]) son[p][u]=++idx;
	     p=son[p][u];
	     cnt[p]++;
	}
	
}
void find(string  s){ //重点核心
	int p=0;
	vector<int> m;
	for(int i=0;s[i];i++){
		int u=getnum(s[i]);
		cnt[son[p][u]]--;
		if(!cnt[son[p][u]]){//如果已经是当前前缀的最后一个字符串;
			int x=1-bf[son[p][u]];//因为它已经是满足条件的最优解,所以把以前的前缀全部删掉
			ans+=x;//答案加上变化
			for(auto d:m){ //遍历他的所有父节点把变化加上 因为父节点的变化就是由各个子节点变过来的
				bf[d]+=x;
			}
			return ;
		}
		//如果没有,就记录这条路径上的所有父节点,等最后处理;
		p=son[p][u];
		m.pb(p);
	}
}



void solved() {
cin>>n;
vector<string> a(n);
for(int i=0;i<n;i++){
	cin>>a[i];
	insert(a[i]);
}
for(int i=0;i<n;i++){
	find(a[i]);
	cout<<ans<<endl;
}


}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

		solved();
	return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值