转换成求逆序对的问题。
如果没有重复的字母,显然是一一对应,用第二个串里对应字符的下标i作为position,然后得到一个position的序列,求这个序列的逆序对个数即为步数。
因为每交换一次,最多少一组逆序对。
(这个position代表一种相对前后的关系,我们只需要处理后使序列中没有逆序对即可。)
当有重复的时候,我们发现,给它一种对应关系即可:第一个a对应第一个a....以此类推。
注意树状数组中不能出现0,否则lowbit会为0,使其陷入死循环。
树状数组求逆序对时可以从后往前,然后add进当前值后,查询当前树状数组中严格小于该值的数即可(sum:1~b[i]-1)。(注意下标为数值,存的为个数)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N=1000005;
typedef long long ll;
int n;
ll ans;
string a,b;
vector<int> v[N];
int id[N],cnt[N],t[N];
int read(){
int num=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
num=num*10+c-'0';
c=getchar();
}
return num*f;
}
int lowbit(int x){
return x&(-x);
}
void add(int x){
for(;x<=n;x+=lowbit(x)){
t[x]+=1;
}
}
int ask(int x){
int res=0;
for(;x;x-=lowbit(x)){
res+=t[x];
}
return res;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n=read();
cin>>a>>b;
for(int i=0;i<n;i++){
v[b[i]-'A'].push_back(i);
}
for(int i=0;i<n;i++){
id[i+1]=v[a[i]-'A'][cnt[a[i]-'A']]+1;
cnt[a[i]-'A']++;
}
for(int i=n;i>=1;i--){
add(id[i]);
ans+=ask(id[i]-1);
}
printf("%lld",ans);
return 0;
}