P2462 [SDOI2007] 游戏

容易发现只与字符串中每个字符出现次数有关,与字符本身的排列无关。

对于一个字符串 SS,能在他后面接龙的不同的出现个数的字符串最多 2626 个。又因为后面的字符串长度比 SS11,所以如果建图是有向无环的。将每个字符出现次数哈希,建图,转化为最长路,DP 即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <set>
#include <cstring>
#include <queue>
#include <map>
#include <vector>
using namespace std;

const int N = 1e5 + 5;
using ull = unsigned long long;

int cnt[N][26];
set<ull> hashing[N];
ull nhash[N];
string s;
int n;
string p[N];
int cnts[26];
int dp[N], from[N];
map<ull, int> maxd;
vector<int> G[N];
int in[N];

int dfs(int u)
{
	if (dp[u]) return dp[u];
	dp[u] = 1;
	for (auto& j : G[u])
	{
		dfs(j);
		if (dp[j] + 1 > dp[u])
		{
			dp[u] = dp[j] + 1;
			from[u] = j;
		}
	}
	//cout << u << " " << dp[u] << "\n";
	return dp[u];
}

int main()
{
	ios::sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr);
	while (cin >> s)
	{
		p[++n] = s;
	}
	for (int i = 1; i <= n; i++)
	{
		memset(cnts, 0, sizeof cnts);
		ull hashings = 0;
		for (auto& j : p[i])
		{
			cnts[j - 'a']++;
		}
		for (int j = 0; j < 26; j++)
		{
			if (cnts[j] > 0)
			{
				cnts[j]--;
				hashings = 0;
				for (int k = 0; k < 26; k++)
				{
					hashings = hashings * 28410841 + cnts[k];
				}
				hashing[i].insert(hashings);
				cnts[j]++;
			}
		}
		hashings = 0;
		for (int k = 0; k < 26; k++)
		{
			hashings = hashings * 28410841 + cnts[k];
		}
		nhash[i] = hashings;
	}
	for (int i = 1; i <= n; i++)
	{
		maxd[nhash[i]] = i;
	}
	for (int i = 1; i <= n; i++)
	{
		for (auto& j : hashing[i])
		{
			if (maxd.count(j))
			{
				G[maxd[j]].emplace_back(i);
				in[i]++;
			}
		}
	}
	for (int i = 1; i <= n; i++)
	{
		if (!in[i]) G[0].emplace_back(i);
	}
	cout << dfs(0) - 1 << "\n";
	int ps = from[0];
	do
	{
		cout << p[ps] << "\n";
		ps = from[ps];
	} while (ps);
	return 0;
}
posted @   HappyBobb  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示