题解:AT_abc483_e [ABC483E] Typo Pairs
思路
可以枚举有
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
string s[200005];
vector<int> a;
bool nxt(int n, int k)
{
int i = k - 1;
while(i >= 0 && a[i] == n - k + i) i--;
if(i < 0) return false;
a[i]++;
for(int j = i + 1; j < k; j++)
a[j] = a[j - 1] + 1;
return true;
}
map<string, int> mp;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> s[i], mp[s[i]]++;
//由于不太可能直接定义 m - 1 维的数组,由于 m 很小,我们可以直接枚举 m 的所有可能性
if(m == 6)
{
a.resize(4);
for(int i = 0; i < 4; i++) a[i] = i;
vector<vector<vector<vector<vector<int> > > > > cnt1;
vector<vector<vector<vector<int> > > > cnt2;
cnt1.resize(26, vector<vector<vector<vector<int> > > >(26, vector<vector<vector<int> > >(26, vector<vector<int> >(26, vector<int>(26, 0)))));
cnt2.resize(26, vector<vector<vector<int> > >(26, vector<vector<int> >(26, vector<int>(26, 0))));
int sum = 0;
do
{
for(int i = 1; i <= n; i++) cnt2[s[i][a[0]] - 'a'][s[i][a[1]] - 'a'][s[i][a[2]] - 'a'][s[i][a[3]] - 'a']++;
for(int i = 0; i < 26; i++) for(int j = 0; j < 26; j++) for(int k = 0; k < 26; k++) for(int l = 0; l < 26; l++)
sum += (cnt2[i][j][k][l] - 1) * cnt2[i][j][k][l] / 2, cnt2[i][j][k][l] = 0;
}
while(nxt(6, 4));
a.resize(5);
for(int i = 0; i < 5; i++) a[i] = i;
do
{
for(int i = 1; i <= n; i++) cnt1[s[i][a[0]] - 'a'][s[i][a[1]] - 'a'][s[i][a[2]] - 'a'][s[i][a[3]] - 'a'][s[i][a[4]] - 'a']++;
for(int i = 0; i < 26; i++) for(int j = 0; j < 26; j++) for(int k = 0; k < 26; k++) for(int l = 0; l < 26; l++) for(int mm = 0; mm < 26; mm++)
sum -= (cnt1[i][j][k][l][mm] - 1) * cnt1[i][j][k][l][mm] * 2, cnt1[i][j][k][l][mm] = 0; //把除以 2 抵消了,变为乘 2
}
while(nxt(6, 5));
for(auto [str, cnt] : mp)
sum += 10 * cnt * (cnt - 1) / 2;
cout << sum << '\n';
}
if(m == 5)
{
a.resize(3);
for(int i = 0; i < 3; i++) a[i] = i;
vector<vector<vector<vector<int> > > > cnt1;
vector<vector<vector<int> > > cnt2;
cnt1.resize(26, vector<vector<vector<int> > >(26, vector<vector<int> >(26, vector<int>(26, 0))));
cnt2.resize(26, vector<vector<int> >(26, vector<int>(26, 0)));
int sum = 0;
do
{
for(int i = 1; i <= n; i++) cnt2[s[i][a[0]] - 'a'][s[i][a[1]] - 'a'][s[i][a[2]] - 'a']++;
for(int i = 0; i < 26; i++) for(int j = 0; j < 26; j++) for(int k = 0; k < 26; k++)
sum += (cnt2[i][j][k] - 1) * cnt2[i][j][k] / 2, cnt2[i][j][k] = 0;
}
while(nxt(5, 3));
a.resize(4);
for(int i = 0; i < 4; i++) a[i] = i;
do
{
for(int i = 1; i <= n; i++) cnt1[s[i][a[0]] - 'a'][s[i][a[1]] - 'a'][s[i][a[2]] - 'a'][s[i][a[3]] - 'a']++;
for(int i = 0; i < 26; i++) for(int j = 0; j < 26; j++) for(int k = 0; k < 26; k++) for(int l = 0; l < 26; l++)
sum -= (cnt1[i][j][k][l] - 1) * cnt1[i][j][k][l] / 2 * 3, cnt1[i][j][k][l] = 0;
}
while(nxt(5, 4));
for(auto [str, cnt] : mp)
sum += 6 * cnt * (cnt - 1) / 2;
cout << sum << '\n';
}
if(m == 4)
{
a.resize(2);
for(int i = 0; i < 2; i++) a[i] = i;
vector<vector<vector<int> > > cnt1;
vector<vector<int> > cnt2;
cnt1.resize(26, vector<vector<int> >(26, vector<int>(26, 0)));
cnt2.resize(26, vector<int>(26, 0));
int sum = 0;
do
{
for(int i = 1; i <= n; i++) cnt2[s[i][a[0]] - 'a'][s[i][a[1]] - 'a']++;
for(int i = 0; i < 26; i++) for(int j = 0; j < 26; j++)
sum += (cnt2[i][j] - 1) * cnt2[i][j] / 2, cnt2[i][j] = 0;
}
while(nxt(4, 2));
a.resize(3);
for(int i = 0; i < 3; i++) a[i] = i;
do
{
for(int i = 1; i <= n; i++) cnt1[s[i][a[0]] - 'a'][s[i][a[1]] - 'a'][s[i][a[2]] - 'a']++;
for(int i = 0; i < 26; i++) for(int j = 0; j < 26; j++) for(int k = 0; k < 26; k++)
sum -= (cnt1[i][j][k] - 1) * cnt1[i][j][k], cnt1[i][j][k] = 0; //除以 2 和乘 2 抵消了
}
while(nxt(4, 3));
for(auto [str, cnt] : mp)
sum += 3 * cnt * (cnt - 1) / 2;
cout << sum << '\n';
}
if(m == 3)
{
a.resize(1);
for(int i = 0; i < 1; i++) a[i] = i;
vector<vector<int> > cnt1;
vector<int> cnt2;
cnt1.resize(26, vector<int>(26, 0));
cnt2.resize(26, 0);
int sum = 0;
do
{
for(int i = 1; i <= n; i++) cnt2[s[i][a[0]] - 'a']++;
for(int i = 0; i < 26; i++)
sum += (cnt2[i] - 1) * cnt2[i] / 2, cnt2[i] = 0;
}
while(nxt(3, 1));
a.resize(2);
for(int i = 0; i < 2; i++) a[i] = i;
do
{
for(int i = 1; i <= n; i++) cnt1[s[i][a[0]] - 'a'][s[i][a[1]] - 'a']++;
for(int i = 0; i < 26; i++) for(int j = 0; j < 26; j++)
sum -= (cnt1[i][j] - 1) * cnt1[i][j] / 2, cnt1[i][j] = 0;
}
while(nxt(3, 2));
for(auto [str, cnt] : mp)
sum += cnt * (cnt - 1) / 2;
cout << sum << '\n';
}
if(m == 2)
cout << n * (n - 1) / 2 << '\n'; //所有字符串都能互相匹配
return 0;
}