Codeforces Round #423 Div. 2 C. String Reconstruction(瞎搞)

题目链接:Codeforces Round #423 Div. 2 C. String Reconstruction

题意:

给你n个子串和出现的位置,让你还原出字典序最小的原串。

数据保证至少有一个解。

题解:

先将所有的串用标号的方式存起来。

然后用将每个子串的出现位置放进对应的桶里。

两个子串ab的位置一共有三种情况:(只考虑a的起点大于b的起点)

一:ab不重叠。

二:ab部分重叠。

三:a子串完全包含后面b子串。

然后开一个标记记录上个出现的子串。

然后扫描整个ans,对于一,二种情况需要更新一下标记。

然后如果当前位置能被上一个出现的子串覆盖,就用上个子串来覆盖。

如果不能就赋值‘a’。

时间复杂度O(maxlen+sum(k))。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 typedef pair<int,int>P;
 5 
 6 const int N=2e6+7;
 7 P a[N];
 8 char s[N],ans[N];
 9 int now=1,n,k,x,ed,mx;
10 vector<int>g[N];
11 
12 int main(){
13     scanf("%d",&n);
14     F(i,1,n)
15     {
16         scanf("%s%d",s+now,&k);
17         int len=strlen(s+now);
18         a[i]=P(now,len);
19         now+=len;
20         F(j,1,k)
21         {
22             scanf("%d",&x);
23             mx=max(mx,x+len-1);
24             g[x].push_back(i);
25         }
26     }
27     int pre=0,idx=0;
28     F(i,1,mx)
29     {
30         for(int &it:g[i])
31         {
32             if(a[it].second+i>a[pre].second+idx)
33                 pre=it,idx=i;
34         }
35         if(a[pre].second+idx-1>=i)ans[i]=s[a[pre].first+i-idx];
36         else ans[i]='a';
37     }
38     printf("%s\n",ans+1);
39     return 0;
40 }
View Code

 

posted @ 2017-07-13 21:22  bin_gege  阅读(162)  评论(0编辑  收藏  举报