农夫约翰的农场布局十分奇特,一条大型的环形道路将奶牛吃草的田地围了起来。
每天早晨,奶牛们穿过这条道路,进入到田地吃草;每天晚上,奶牛们穿过这条道路,离开田地,返回牛棚休息。
众所周知,奶牛是有习性的动物,每头奶牛每天通过道路的方式都相同。
每头奶牛每天固定地从道路的某一位置进入田地,从道路的另一不同位置离开田地。
所有奶牛的所有进出位置之间互不相同。
约翰共有 头奶牛,依次命名为 。
因此,道路上共有 个不同的进出位置。
约翰沿着环形道路按顺时针方向扫描了每个位置,并记录了每个位置处经过的奶牛的名字,最终形成了一个包含 个字母的序列, 中的每个字母恰好出现两次。
他并没有记录哪些位置是入口,哪些位置是出口。
看着地图上记录的这些位置,约翰想要知道一天当中,有多少对奶牛之间的从入口穿过田地到达出口的路径可能会存在交叉。
如果奶牛 从入口穿过田地到达出口的路径必须穿过奶牛 从入口穿过田地到达出口的路径,那么称这对牛 是“交叉”对。
请帮助约翰计算“交叉”对(不考虑顺序,即 与 视为同一对 )的总数。
输入格式
共一行,包含一个长度为 的只包含大写字母的字符串,其中每个字母恰好出现两次。
输出格式
输出交叉对的总数。
输入样例:
ABCCABDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ
输出样例:
1
样例解释
在此样例中,只有 和 一对交叉对。
解法一
using namespace std;
char str[100];
int pos[100];
int solve(int a, int b){
int q[30] = {0};
for(int i = a; i <= b; i++) q[str[i] - 'A']++;
int res = 0;
for(int i = 0; i < 26; i++)
if(q[i] == 1) res++;
return res;
}
int main(){
scanf("%s", str + 1);
int res = 0;
for(int i = 1; i <= 56; i++){
int x = str[i] - 'A';
if(!pos[x]) pos[x] = i;
else res += solve(pos[x] + 1, i - 1);
}
cout << res / 2 << endl;
return 0;
}
解法二
using namespace std;
vector<int> p[26];
int main(){
string s;
cin >> s;
for(int i = 0; i < s.size(); i++)
p[s[i]-'A'].push_back(i);
int res = 0;
for(int i = 0; i < 26; i++){
for(int j = i + 1; j < 26; j++){
int cnt = 0;
for(auto y: p[j])
if(p[i][0] < y && y < p[i][1])
cnt++;
if(cnt == 1) res++;
}
}
cout << res << endl;
return 0;
}