codeforces 828 c String Reconstruction(扫描线+string)

来源:互联网 发布:c语言单片机培训班 编辑:程序博客网 时间:2024/05/29 16:22

题意:

给出一个字符串的n个子串,并且给出这n个子串在原串里出现的位置,现在让构造出一个字符串符合题目的给定的条件,并且字典序最小。


解题思路:

直接xjb填子串的话肯定是超时的,所以要想办法避免重复的填。

其实很简单,在每个位置上都放一个标记,标记这里有一个长度为len的子串,然后我们o(n)扫一遍就可以了,标记的时候可能有重复,我们留下len最长的那一个就可以。


然后标记的时候,你如果真的把整个字符串放上去,就mle了,可以先把n个字符串记录下来,然后只标记字符串对应的编号就可以。


一开始我以为记录n个字符串也存不下,所有mle之后直接就弃疗了,其实题目里说了字符串总长度不超过1e6,所以开1e5(n的范围)个string就可以记录下来了,毕竟string是动态内存的。


然后还存在一个上届问题,就是构造出来的字符串上届,字符串总长度不超过1e6,但是原字符串并没有说,但是题目又说了,子串出现的起始位置的不超过1e6,那么最后构造出来的字符串长度就一定不超过2e6了。范围也构造出来了。


这个题扫描线o(n)扫一遍处理其实蛮好想的,关键在于我没有好好读题,以为怎么存都存不下这么多字符串mle了,然后就弃疗了,然后上届也是要好好读题才能确定下来的。读题很重要啊!


代码:

#include <bits/stdc++.h>#define ps push_backusing namespace std;const int maxn=2e6+1e5;char str[maxn];struct node{    string s;    int len;}t[maxn];int l[maxn];char s[maxn];vector<int>a[maxn];int main(){    ios::sync_with_stdio(false);    int n, i, j, k, pos, ma=0, e;    cin>>n;    for(i=0; i<n; i++)    {        cin>>t[i].s;        t[i].len=(int)t[i].s.length();        cin>>k;        for(j=0; j<k; j++)        {//            scanf("%d", &pos);            cin>>pos;            ma=max(ma, pos+t[i].len-1);            {            if((int)a[pos].size()>0)            {                if(t[a[pos][0]].len<t[i].len)                {                    a[pos][0]=i;                }            }            else a[pos].ps(i);            }        }    }    if(ma>maxn)return 0*printf("%d\n", ma);    int tmp;    for(i=1; i<=ma; i++)    {        if((int)a[i].size()>0)        {            tmp=a[i][0];            for(j=0; j<t[tmp].len; j++, i++)            {                str[i]=t[tmp].s[j];                if(j>0 && (int)a[i].size()>0 && t[a[i][0]].len>(t[tmp].len-j))break;            }            i--;        }        else str[i]='a';    }    str[i]='\0';    cout<<str+1<<endl;//    printf("%s\n", str+1);    return 0;}


阅读全文
0 0
原创粉丝点击