你有一个字符串a和一个字符串b,两个字符串的长度都是n。在字符串a中最多有10个不同的字符。你还有一个集合Q。最初,集合Q是空的。您可以对字符串应用以下操作任意次数:选择索引i (1 < i< n)和小写英文字母c,将a添加到集合Q中,然后将a替换为c。例如,设字符串a为“abecca”。我们可以做以下操作:在第一个操作中,如果你选择i = 3和c = x,字符as = e将被添加到集合Q中。因此,集合Q将是{e},字符串a将是"abxcca"。在第二个操作中,如果你选择i=6和c=s,字符a6=a将被添加到集合Q中。因此,集合Q将是{e, a},字符串a将是"abxccs"。您可以对a应用任意数量的操作,但最终,集合Q应该包含最多k个不同的字符。在这个约束条件下,你必须最大化整数对(l, r)的数量(1 <l <r< n),使得a[l, r] = b[l, r]。这里,s[l, r]表示字符串s的子字符串,从索引I(含)开始,到索引r(含)结束。输入每个测试包含多个测试用例。第一行包含测试用例的数量t (1 < t < 104)。测试用例的描述是流畅的。第一行包含两个整数n和k (1 <n <105,0<k<10)——两个字符串的长度和不同Q的极限。集合中的字符第二行是长度为n的字符串a。字符串a中最多可以包含10个不同的字符。最后一行包含长度为n的字符串b。字符串a和b都只包含小写英文字母。所有测试用例的n和不超过105。输出对于每个测试用例,在一行中打印一个整数,即满足约束的最大对数(I, r)。例子
input
Copy
6
3 1
abc
abd
3 0
abc
abd
3 1
xbb
xcd
4 1
abcd
axcb
3 10
abc
abd
10 3
lkwhbahuqa
qoiujoncjb
output
Copy
6 3 6 6 6 11
请注意在第一种情况下,我们可以选择索引i = 3,并将其替换为字符c = d。所有可能的对(l, r)都是有效的。在第二种情况下,我们不能进行任何操作。3对有效的(l, r)是:1. A [1,1] = b[1,1] = " A ",2. A [1,2] = b[1,2] = "ab",3.A [2,2] = b[2,2] = "b"。在第三种情况下,我们可以选择索引2和索引3,并分别将它们替换为字符c和d。最终的集合Q将是{b},其大小为1,满足k的值。所有可能的对(l, r)都是有效的。
题解:
根据题中所给数据发现可供我们修改的字母种类k只有十,并且原来字符串中的字母种类cnt也只有10
1.如果k >= cnt
a可以和b变的一样,所以l,r的对数是n*(n-1)/2 + n
2.如果k < cnt
我们发现选取的种类数是从十种里面选五个,最多只要252种情况
而n的只有1e5,所以直接DFS找的所以情况,取最大值即可
关键是如何DFS
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
using namespace std;
#define int long long
const int N = 6e5 + 10;
string s;
int n,k;
int vis[30];
map<char,int> ff;
int ans = 0,cnt = 0;
string a,b;
void dfs(int i1,int cnt1)
{
if(i1 > cnt)
{
if(cnt1 == k)
{
int sum = 0;
int t = 0;
for(int i = 0;i < n;i++)
{
if(a[i] == b[i]||vis[a[i] - 'a'])
sum++;
else
t += sum*(sum + 1)/2,sum = 0;
}
t += sum*(sum + 1)/2;
ans = max(ans,t);
}
}
else
{
dfs(i1 + 1,cnt1);
vis[s[i1] - 'a'] = 1;//第i1个字母拿过了
if(cnt1 < k)
dfs(i1 + 1,cnt1 + 1);//如果cnt1 < k要修改的字母种类还不够
vis[s[i1] - 'a'] = 0;
}
}
void solve()
{
cin >> n >> k;
cin >> a >> b;
map<char,int> f;
memset(vis,0,sizeof vis);
cnt = 0;
ans = 0;
s = "";
for(auto c:a)
{
if(!f[c])
{
s = s + c;
f[c] = 1;
cnt++;
}
}
if(cnt <= k)
{
cout << n*(n+1)/2 <<"\n";
return ;
}
s = " " + s;
dfs(1,0);
cout << ans <<"\n";
}
signed main()
{
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}