ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 B. Tomb Raider

题解

给你n个串 这n个串都看作一个环 问n个串的最长公共子序列(不连续) 输出字典序最小的一个

暴力枚举第一个串的子序列(最多2^8个) 然后用string和rotate暴力尝试答案是否正确 最后找字典序最小 注意只有一个串的时候也需要找字典序最小

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int n;
	while (cin >> n)
	{
		string s[20];
		vector<string> ans;
		for (int i = 0; i < n; i++)
			cin >> s[i];
		if (n == 1)
		{
			string res(s[0].size(), 'z');
			for (int j = 0; j < s[0].size(); j++)
			{
				if (s[0] < res)
					res = s[0];
				rotate(s[0].begin(), s[0].begin() + 1, s[0].end());
			}
			cout << res << endl;
			continue;
		}
		for (int i = (1 << s[0].size()) - 1; i >= 1; i--) //子串掩码
		{
			string sub;
			for (int j = 0; j < s[0].size(); j++)
				if (i & (1 << j))
					sub.push_back(s[0][j]);
			//cout << endl; /
			for (int j = 0; j < sub.size(); j++) //子串旋转
			{
				int can = 1; //全部满足
				for (int k = 1; k < n && can; k++) //其它串
				{
					int flag = 0; //一个位置满足
					for (int l = 0; l < s[k].size() && !flag; l++) //其它串旋转 
					{
						int last = -1, cnt = 0; //上次位置 匹配个数
						for (int p = 0; p < sub.size(); p++) //s[k]找sub
							for (int q = last + 1; q < s[k].size(); q++)
								if (sub[p] == s[k][q])
								{
									last = q, cnt++;
									break;
								}
						if (cnt == sub.size())
							flag = 1;
						rotate(s[k].begin(), s[k].begin() + 1, s[k].end());
					}
					if (!flag)
						can = 0;
				}
				if (can)
				{
					if (!ans.empty() && sub.size() > ans[0].size())
						ans.clear();
					if (ans.empty() || sub.size() == ans[0].size())
						ans.push_back(sub);
					break;
				}
				rotate(sub.begin(), sub.begin() + 1, sub.end());
			}
		}
		if (ans.size())
		{
			string res(ans[0].size(), 'z');
			for (int i = 0; i < ans.size(); i++)
			{
				for (int j = 0; j < ans[0].size(); j++)
				{
					if (ans[i] < res)
						res = ans[i];
					rotate(ans[i].begin(), ans[i].begin() + 1, ans[i].end());
				}
			}
			cout << res << endl;
		}
		else
			cout << 0 << endl;
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值