题意

给定一个长度为 \(n\) 小写英文字母组成的字符串 \(s\)。可以任意选定 \(1\le x\le y\le n\),把 \(s_x\)\(s_y\) 之间的字符翻转。 求最终不同字符串的方案数。

分析

我们先考虑所有字符都不同的情况。

小学奥数的加法原理告诉我们,每一位都不同的字符串,对于第 \(i\) 位,可以增加 \(i-1\) 种翻转方案。

再考虑加入相同的情况。

\(s=abcad\),若翻转 \([1,4]\),和翻转 \([2,3]\) 等效。同理,每一组相同字符都要给答案减一。

用一个桶记录每种字母出现次数,总时间复杂度 \(O(|s|)\)

Code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
string s;
ll n,sum[200],ans=1;
signed main(){
    cin>>s;
    n=s.size();
    for(ll i=0;i<n;++i){
        ++sum[s[i]];
        ans+=i+1-sum[s[i]];
    }
    printf("%lld",ans);
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。