Codeforces Round #445 (Div. 2): D. Restoration of string(模拟)

本文介绍了一种算法,用于解决给定多个字符串时构造一个最终字符串的问题,使得这些字符串成为终串的最平凡子串。文章详细阐述了解题思路与实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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.

Output

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.

Examples
input
4
mail
ai
lru
cf
output
cfmailru
input
3
kek
preceq
cheburek
output
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
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值