CCUT应用OJ——小龙的字符串函数

题目简介

  • 题源:1073 - 小龙的字符串函数 | CCUT OJ
  • 题意:给定 \(n\) 个等长字符串,定义函数 \(f(s_i,s_j)\) 表示字符串 \(s_i\)\(s_j\) 中位置和字符相同的总数。输出 \(\sum f(s_i,s_j)\) ( 其中 \(i<j\) )。
  • 数据范围:\(1\le n\le 2000,1\le |s_i|\le 2000\)
  • 注:若无特殊说明,博主的代码模板如下,通过 solve 函数处理多组测试用例。本文后续代码仅给出 solve 函数。
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define ln '\n'

int solve(){

}

int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	int T;cin>>T;
	while(T--){
		cout<<solve()<<ln;
	}
	return 0;
}

朴素想法

朴素想法极其简单,双循环两两遍历字符串,逐位检查是否相同即可。复杂度 \(O(n^2 \cdot |s_i|)\),超时。

int solve(){
	int n;cin >> n;
	vector<string> strs(n);
	for (auto &i:strs) cin >> i;
	int L = strs[0].size();
	i64 ans = 0;
	for (int i = 0; i < n; i++) 
	    for (int j = i + 1; j < n; j++) 
	        for (int k = 0; k < L; k++) 
	            if (strs[i][k] == strs[j][k]) 
	                ans++;
	return ans;
}

题解

定义权值数组 cnt[i][26],表示这些字符串第 \(i\) 位上各字母出现的频率。根据排列组合知识,假设字符 \(j\) 在第 \(i\) 位上出现了 cnt[i][j] 次,则其在该位上可两两配对的次数为\(C_{cnt[i][j]}^2=\dfrac{cnt[i][j]\cdot (cnt[i][j]-1)}{2}\) 次。时间复杂度 \(O(n \cdot|s_i|\cdot 26)\)

int solve() {
	int n; cin >> n;
	vector<string> strs(n);
	for (auto &i:strs) cin >> i;
	int L = strs[0].size();
	int cnt[2000][26] = {0};
	for (int k = 0; k < n; k++)
	    for (int i = 0; i < L; i++)
	        cnt[i][strs[k][i]-'a']++;
	i64 ans = 0;
	for (int i = 0; i < L; i++)
	    for (int j = 0; j < 26; j++)
	        ans += 1LL * cnt[i][j] * (cnt[i][j]-1) / 2;
	return ans;
}
posted @ 2025-10-30 21:09  椰萝Yerosius  阅读(5)  评论(0)    收藏  举报