题意:给你n个串,给你每个串在总串中开始的每个位置,问你最小字典序总串。
思路:显然这道题有很多重复填涂的地方,那么这里的时间花费就会特别高。
我们维护一个并查集fa,用fa[i]记录从第i位置开始第一个没填涂的位置,那每次都能跳过涂过的地方。每次填完当前格就去填find(fa[i + 1])。
ps:一定要合并,不然超时。
代码:
#include<stack> #include<vector> #include<queue> #include<set> #include<cstring> #include<string> #include<sstream> #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #define ll long long #define ull unsigned long long using namespace std; const int maxn = 1000000+5; const int seed = 131; const int MOD = 100013; const int INF = 0x3f3f3f3f; char ans[maxn*10]; int fa[maxn*10]; char s[maxn]; int find(int x){ return fa[x] == x? x : fa[x] = find(fa[x]); } int main(){ int n,t; memset(ans,0,sizeof(ans)); scanf("%d",&n); for(int i = 0;i < maxn * 10;i++) fa[i] = i; int end = 1; while(n--){ scanf("%s%d",s,&t); int len = strlen(s); while(t--){ int x; scanf("%d",&x); end = max(end,x + len - 1); for(int i = find(x);i <= x + len -1;i = find(i + 1)){ ans[i] = s[i - x]; int fx = find(i); int fy = find(i + 1); if(fx > fy) fa[fy] = fx; else fa[fx] = fy; } } } for(int i = 1;i <= end;i++) if(ans[i] != 0)printf("%c",ans[i]); else printf("a"); printf("\n"); return 0; }
原文地址:https://www.cnblogs.com/KirinSB/p/9517004.html
时间: 2024-10-09 05:22:42