A substring of some string is called the most frequent, if the number of its occurrences is not less than number of occurrences of any other substring.
You are given a set of strings. A string (not necessarily from this set) is called good if all elements of the set are the most frequent substrings of this string. Restore the non-empty good string with minimum length. If several such strings exist, restore lexicographically minimum string. If there are no good strings, print "NO" (without quotes).
A substring of a string is a contiguous subsequence of letters in the string. For example, "ab", "c", "abc" are substrings of string "abc", while "ac" is not a substring of that string.
The number of occurrences of a substring in a string is the number of starting positions in the string where the substring occurs. These occurrences could overlap.
String a is lexicographically smaller than string b, if a is a prefix of b, or a has a smaller letter at the first position where a and b differ.
The first line contains integer n (1 ≤ n ≤ 105) — the number of strings in the set.
Each of the next n lines contains a non-empty string consisting of lowercase English letters. It is guaranteed that the strings are distinct.
The total length of the strings doesn't exceed 105.
Print the non-empty good string with minimum length. If several good strings exist, print lexicographically minimum among them. Print "NO" (without quotes) if there are no good strings.
4 mail ai lru cf
cfmailru
3 kek preceq cheburek
NO
题意:
给你n个字符串,让你构造一个终串,使得这n个字符串都是终串的最平凡子串,如果不存在输出NO
最平凡子串:出现次数最多的子串
思路:
①很显然如果某个子串中有两个相同的字符,答案一定是NO
②如果两个不同的子串中有相同的字符
那么这两个子串一定可以通过拼在一起使得每个字符都只出现1次(也就是一个串的前缀和另一个串的后缀相同)
如果不能拼也是NO
这样思路就明显了:对于每个串先检查是否每个字符都独一无二
然后再暴力所有字符串看是否能和其中一个拼起来
注意拼起来之后要继续拼!直到对于所有字符串所有字符都只出现一次
中间出现任何问题都是NO
代码写丑了
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int cnt[33];
char str[100005], ans[60][60];
typedef struct Res
{
char str[60];
bool operator < (const Res &b) const
{
if(strcmp(str+1, b.str+1)<0)
return 1;
return 0;
}
}Word;
Word s[60];
int main(void)
{
int n, i, j, k, p, q, len;
scanf("%d", &n);
k = 0;
for(i=1;i<=n;i++)
{
scanf("%s", str+1);
len = strlen(str+1);
if(len>=27)
{
printf("NO\n");
return 0;
}
loop:
for(j=1;j<=k;j++)
{
if(strchr(ans[j]+1, str[len])!=NULL && strchr(ans[j]+1, str[1])==NULL)
{
for(p=1;p<=56;p++)
swap(ans[j][p], str[p]);
len = strlen(str+1);
if(strchr(ans[j]+1, str[1])==NULL)
{
printf("NO\n");
return 0;
}
}
if(strchr(ans[j]+1, str[1])!=NULL)
{
for(p=1;ans[j][p]!=str[1];p++);
for(q=1;q<=len;q++)
{
if(ans[j][p+q-1]!=str[q] && ans[j][p+q-1]!=0)
{
printf("NO\n");
return 0;
}
ans[j][p+q-1] = str[q];
}
memset(str, 0, sizeof(str));
break;
}
}
if(j!=k+1)
{
for(p=1;p<=56;p++)
swap(ans[j][p], ans[k][p]);
for(p=1;p<=56;p++)
swap(ans[k][p], str[p]);
len = strlen(str+1);
k--;
goto loop;
}
if(j==k+1)
{
k++;
for(p=1;p<=56;p++)
swap(ans[k][p], str[p]);
j = k;
}
memset(cnt, 0, sizeof(cnt));
for(p=1;p<=len;p++)
{
if(cnt[ans[j][p]-'a']==1)
{
printf("NO\n");
return 0;
}
cnt[ans[j][p]-'a'] = 1;
}
}
memset(cnt, 0, sizeof(cnt));
for(i=1;i<=k;i++)
{
for(j=1;ans[i][j]!='\0';j++)
s[i].str[j] = ans[i][j];
for(j=1;s[i].str[j]!='\0';j++)
{
if(cnt[s[i].str[j]-'a']==1)
{
printf("NO\n");
return 0;
}
cnt[s[i].str[j]-'a'] = 1;
}
}
sort(s+1, s+k+1);
for(i=1;i<=k;i++)
printf("%s", s[i].str+1);
puts("");
return 0;
}
/*
3
swt
nmz
zs
*/