1. 程式人生 > >ACM/ICPC 2018亞洲區預選賽北京賽站網路賽 B. Tomb Raider

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; }