自创分治做法WA57pts求助
查看原帖
自创分治做法WA57pts求助
637796
Xy_top楼主2023/10/26 22:01

rtrt,思路很简单,对每位分每个字母考虑,然后顺便记录当前已知谁的字母序小于谁的字母序。

#include <bits/stdc++.h>
#define int long long
#define For(i, a, b) for (int i = (a); i <= (b); i ++)
#define foR(i, a, b) for (int i = (a); i >= (b); i --)
using namespace std;
int n;
string s[30005];
int f[27][27];//f[i][j]:字母 i 是否小于字母 j
vector <int> ans;
void work (int i, vector <int> v) {
	if (!v.size () ) return;
	if (v.size () == 1) {
		ans.push_back (v[0]);
		return;
	}
	bool vis[27];
	For (i, 1, 26) vis[i] = 0;
	bool ff = 0;
	For (j, 0, v.size () - 1) {
		if (s[v[j] ].size () == i) {
			ff = 1;
			ans.push_back (v[j]);
		}
		else vis[s[v[j] ][i] ] = 1;
	}
	if (ff) return;
	For (j, 1, 26) {
		if (!vis[j]) continue;
		vector <int> c;
		bool fi = 0;
		For (k, 1, 26) if (f[k][j] && vis[k]) {
			fi = 1;
			break;
		}
		if (fi) continue;
		For (k, 0, v.size () - 1) {
			if (s[v[k] ].size () == i || s[v[k] ][i] != j) continue;
			c.push_back (v[k]);
		}
		For (k, 1, 26) if (vis[k] && j != k) ++ f[j][k];
		if (c.size () ) work (i + 1, c);
		For (k, 1, 26) if (vis[k] && j != k) -- f[j][k];
	}
}
void solve () {
	cin >> n;
	For (i, 1, n) {
		cin >> s[i];
		For (j, 0, s[i].size () - 1) s[i][j] -= 'a' - 1;
	}
	For (i, 1, 26) {
		vector <int> v;
		For (j, 1, n) {
			if (s[j][0] == i) v.push_back (j);
			else ++ f[i][s[j][0] ];
		}
		work (1, v);
		For (j, 1, n) if (s[j][0] != i) -- f[i][s[j][0] ];
	}
	sort (ans.begin (), ans.end () );
	cout << ans.size () << '\n';
	For (i, 0, ans.size () - 1) {
		For (j, 0, s[ans[i] ].size () - 1)
			cout << char (s[ans[i] ][j] + 96);
		cout << '\n';
	}
}
signed main () {
	int _ = 1;
//	cin >> _;
	while (_ --) {
		solve ();
		cout << '\n';
	}
	return 0;
}
2023/10/26 22:01
加载中...