本文共 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)[当然不算sort了hh]
#includeusing 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)稍微差一点点
#includeusing 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}Ⅲ.妙用并查集 Ⅲ.妙用并查集
思路和上面别无二致,就是用并查集来实现而已
#includeusing 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!