链接:https://www.nowcoder.com/acm/contest/148/J
来源:牛客网
Rikka with Nickname
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
Sometimes you may want to write a sentence into your nickname like "lubenwei niubi". But how to change it into a single word? Connect them one by one like "lubenweiniubi" looks stupid.
To generate a better nickname, Rikka designs a non-trivial algorithm to merge a string sequence s1...sn into a single string. The algorithm starts with s=s1 and merges s2...sn into s one by one. The result of merging t into s is the shortest string r which satisfies s is a prefix of r and t is a subsequence of r.(If there are still multiple candidates, take the lexicographic order smallest one.)
String s is a prefix of r if and only if |s| ≤ |r| and for all index i ∈ [1, |s|], si = ri.
String s is a subsequence of r if and only if there is an index sequence which satisfies
.
For example, if we want to generate a nickname from "lubenwei niubi", we will merge "niubi" into "lubenwei", and the result is "lubenweiubi".
Now, given a sentence s1...sn with n words, Rikka wants you to calculate the resulting nickname generated by this algorithm.
输入描述:
The first line contains a single number t(1 ≤ t ≤ 3), the number of testcases. For each testcase, the first line contains one single integer n(1 ≤ n ≤ 106). Then n lines follow, each line contains a lowercase string .
输出描述:
For each testcase, output a single line with a single string, the result nickname.
示例1
输入
复制
2 2 lubenwei niubi 3 aa ab abb
输出
复制
lubenweiubi aabb
题意:给你n个字符串(总长度不超过1e6)。你要把这n个字符串按输入顺序合并成一个。
假设第i+1个字符串和前i个合并后个字符串合并:去掉第i+1个字符串的 是前i个合并后个字符串 的 子序列 的 最长前缀 。
思路:我用的是set模拟。维护26个字母的set,每次把出现的位置i加入到set[s[i]-'a']中。然后每合并一个字符串,就lower_bound每一个字母,查询是否存在下标j<i再set中。是就继续找下一个字符,不是就跳出。记录一下可以合并的位置即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1000010;
int n,m,k;
int a[maxn],sum[maxn];
int c[maxn];
int ans,ct,cnt,tmp,flag;
char s[maxn];
string ss;
set<int>st[26];
set<int>::iterator it,itt;
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ans=0; flag=1;
ss="";
int f=0,len=0;
for(int i=0;i<maxn;i++) c[i]=0;
for(int i=0;i<26;i++)st[i].clear();
for(int i=0;i<n;i++){
scanf("%s",s);
int l=strlen(s),x=0;
f++;
for(int j=0;j<l;j++)
{
int id=s[j]-'a';
it=st[id].lower_bound(x);
if(it==st[id].end()) break;
else c[j]=f;
x=*it+1;
}
for(int j=0;j<l;j++)
if(c[j]!=f) {
ss+=s[j];
st[s[j]-'a'].insert(len);
len++;
}
}
printf("%s\n",ss.c_str());
// if(flag) puts("YES"); else puts("NO");
}
return 0;
}