P2462 [SDOI2007] 游戏
容易发现只与字符串中每个字符出现次数有关,与字符本身的排列无关。
对于一个字符串 ,能在他后面接龙的不同的出现个数的字符串最多 个。又因为后面的字符串长度比 多 ,所以如果建图是有向无环的。将每个字符出现次数哈希,建图,转化为最长路,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;
}

浙公网安备 33010602011771号