Logo cybrex 的博客

博客

题解:CF777D Cloud of Hashtags

...
cybrex
2025-12-01 12:49:51

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2025-09-02 19:31:32

怎么没人写字典树?我来补一篇。

发现要使字符串序列字符串序列最小,则对于两个相邻的字符串 $s_i$,$s_j$,$s_{i,k}\le s_{j,k}$,不难发现用字典树倒序插入是好维护的,只需在字典树上每遍历到一个节点,判断是否本节点下一层已存在比当前字符字典序更小的字符即可。

发现难以处理字符串长度不一的情况,这时我们只需标记字符串结尾为一个独立节点,使其小于所有字符,每次额外判断即可。

复杂度 $O(n\times26)$,$n$ 为字符串总长度。

#include<bits\/stdc++.h>
#define endl '\n'
using namespace std;
const int N=5e5+10;
int t[N][30];
int cnt;
string ans[N];
void ins(string s,int xx){
	int u=0;
	int w=-1;
	for(int i=0;i<s.size()-1;i++){
		int x=s[i]-'a'+1;
		bool mx=0;
		for(int j=x-1;j>=0;j--){
			if(t[u][j]){
				mx=1;break; 
			}
		}
		if(mx){
			break;
		}
		if(!t[u][x]){
			t[u][x]=++cnt;
		}
		u=t[u][x];
		w=i;
	}
	t[u][0]=++cnt;
	ans[xx]='#';
	for(int i=0;i<=w;i++){
		ans[xx]+=s[i];
	}
} 
string S[N];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		string s;cin>>s;
		for(int i=0;i<s.size();i++){
			s[i]=s[i+1];
		}
		S[i]=s;
	}
	for(int i=n;i>=1;i--){
		ins(S[i],i);
	}
	for(int i=1;i<=n;i++){
		cout<<ans[i]<<endl;
	}
	return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。