题目链接: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 ",ans+1); 39 return 0; 40 }