A. String Reconstruction(三种解法,排序贪心或跳步或并查集)
发布日期:2021-06-30 10:17:59 浏览次数:2 分类:技术文章

本文共 2491 字,大约阅读时间需要 8 分钟。

这题看了下有很多解法,一步一步来

Ⅰ . 区 间 贪 心 排 序 \color{Red}Ⅰ.区间贪心排序 .

这是自己想的,而且似乎没看到有人用?(明明相对最容易想到)

把 每 个 字 符 串 出 现 的 每 个 位 置 记 作 一 个 区 间 \color{orange}把每个字符串出现的每个位置记作一个区间

如 果 按 照 左 端 点 排 序 , 那 就 记 录 当 前 匹 配 到 的 最 右 端 点 l a s t 如果按照左端点排序,那就记录当前匹配到的最右端点last ,last

那 么 这 个 区 间 有 贡 献 的 地 方 就 是 [ l a s t + 1 , r ]    ( r 为 区 间 右 端 点 ) 那么这个区间有贡献的地方就是[last+1,r]\ \ (r为区间右端点) [last+1,r]  (r)

由 于 l 是 递 增 的 , 所 以 不 可 能 漏 掉 解 , 复 杂 度 O ( n ) [ 当 然 不 算 s o r t 了 h h ] 由于l是递增的,所以不可能漏掉解,复杂度O(n)[当然不算sort了hh] l,,O(n)[sorthh]

#include 
using namespace std;const int maxn=2e6+10;struct p{ int l,r,id; bool operator < (const p&tmp ) const{ return l
> n; for(int i=1;i<=n;i++) { cin >> s[++id] >> k; for(int j=1;j<=k;j++) { cin >> a[++top].l; a[top].id=id,a[top].r=a[top].l+s[id].length()-1; } } sort(a+1,a+1+top); int last=a[1].l; for(int i=1;i<=top;i++) { last=max(last,a[i].l); for(;last<=a[i].r;last++) { int index = last-a[i].l; w[last]=s[ a[i].id ][index]; } } for(int j=1;j<=last-1;j++) if(w[j]>='a'&&w[j]<='z') cout<

Ⅱ . 记 录 后 缀 跳 步 走 \color{Red}Ⅱ.记录后缀跳步走 .

这种解法也很妙啊

还是把每个串出现的位置当成那个区间

一般来说需要把整个字符串一个一个填进去

考虑到很多地方已经被填过了

我们设置一个 p r e [ i ] pre[i] pre[i]数组,表示 i i i以后第一个没被填过的位置

这 样 可 以 一 直 跳 着 走 , 复 杂 度 比 O ( n ) 稍 微 差 一 点 点 这样可以一直跳着走,复杂度比O(n)稍微差一点点 ,O(n)

#include 
using namespace std;const int maxn=2e6+10;int n,k,pre[maxn],f[maxn],maxx;char s[maxn],a[maxn];int main(){ cin >> n; for(int i=0;i
> (a+1) >> k; int len = strlen(a+1); for(int j=1;j<=k;j++) cin >> f[j]; for(int j=1;j<=k;j++) { int l=f[j],r=f[j]+len-1; maxx=max(maxx,r); while(1) { if(l>=f[j]+len) break; if(pre[l]==l)//直接赋值啦!! { s[l]=a[l-f[j]+1]; pre[l]=pre[r+1];//本区间都会被填充 l++; } else { int q=pre[l]; pre[l]=pre[q];//关键的一步,跳之前更新 l=q; } } } } for(int i=1;i<=maxx;i++) printf("%c",(pre[i]==i)?'a':s[i]);}

Ⅲ . 妙 用 并 查 集 \color{red}Ⅲ.妙用并查集 .

思路和上面别无二致,就是用并查集来实现而已

#include 
using namespace std;const int maxn=2e6+10;char ans[maxn];int pre[maxn],maxx,n,k;int find(int x){ return pre[x]==x?pre[x]:pre[x]=find(pre[x]);}void join(int q,int w){ pre[find(q)]=find(w);}int main(){ for(int i=0;i
> n; for(int i=1;i<=n;i++) { string s; cin >> s >> k; int len=s.size(),l; for(int j=1;j<=k;j++) { cin >> l;//开始的位置 maxx=max(maxx,l+len-1); int last=find(l);//下一个没被赋值的点 while(last

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/107213955 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:A. Office Keys(二分+思维贪心含证明)
下一篇:K. Travel Cards(暴力)

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月06日 02时19分41秒