Codeforces Round #423 C. String Reconstruction

题目链接: String Reconstruction

题目大意

猜一个字符串, 告诉你n个子串, 告诉你这些子串在原字符串出现的次数和出现的位置, 求字典序最小的原字符串
数据规模: 106,n105,106

思路

因为题目数据比较大, 如果纯暴力会TLE, 但原字符串长度 2106 , 所以我们只要保证还原字符串的时候不要重复就好了
使用一个类似与并查集的par数组和find()函数, par[x]记录的是下一个需要更新的位置, par[x]==x代表这个位置还没有更新, 每次更新完s[x]后, 让par[x] = x+1, find(x)可以找到已经更新的最远位置+1, 然后利用路径压缩减少复杂度

代码

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 5E6;
char s[MAXN], t[MAXN];
int par[MAXN];
int find(int x) { return x == par[x] ? x : par[x]=find(par[x]); }
int main()
{
    int n, m, x, ma = 0;
    for(int i=0; i<MAXN; ++i) par[i] = i;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%s%d", t, &m);
        int len = strlen(t);
        while(m--)
        {
            scanf("%d", &x);
            --x;
            ma = max(ma, x+len);
            int y = x;
            while((y=find(y)) < x+len)
            {
                s[y] = t[y-x];
                par[y] = y+1;
            }
        }
    }
    for(int i=0; i<ma; ++i) putchar(s[i] ? s[i] : 'a');
    cout << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值