# 单词分析
# 题目:
给定一个只包含小写字母的字符串,要找出该字符串中出现次数最多的、字典序最小的 字母,输出该字母及该字母出现的次数。
# 分析
(1)统计每个字母出现的次数。
(2)找出出现次数最多、字典序最小的字母。
# 代码
#include<bits/stdc++.h> | |
using namespace std; | |
int cnt[]; | |
signed main(){ | |
string s; | |
cin >> s; | |
for(int i = 0; i < s.size() ; i ++) cnt[s[i] - 'a'] ++ ; // 'a' = | |
char ans1 = 0; int ans2 = 0; | |
for(int i = 0; i < 26; i ++){ | |
if(cnt[i] > ans) ans1 = cnt[i] , ans2 = (i + 'a'); // 'a' = ; | |
} | |
cout << ans1 << '\n' << ans2 << '\n'; | |
return ; | |
} |
# 人物相关性分析
# 题目
【问题描述】 小明正在分析一本小说中的人物相关性。他想知道在小说中 Alice 和 Bob 有多少次 同时出现。 更准确地说,小明定义 Alice 和 Bob “同时出现” 的意思是在小说文本中 Alice 和 Bob 之间不超过 K 个字符。 例如以下文本: This is a story about Alice and Bob. Alice wants to send a private message to Bob. 假设 K = 20,则 Alice 和 Bob 同时出现了 2 次,分别是 “Alice and Bob” 和 “Bob. Alice”。前者 Alice 和 Bob 之间有 5 个字符,后者有 2 个字符。 注意:・Alice 和 Bob 是大小写敏感的,alice 或 bob 等并不计算在内。・Alice 和 Bob 应为单独的单词,前后可以有标点符号和空格,但是不能有字母。 例如 Bobbi 并不算出现了 Bob。
【输入格式】 第一行包含一个整数 K (1 ⩽ K ⩽ 106)。 第二行包含一行字符串,只包含大小写字母、标点符号和空格。长度不超过 106。
【输出格式】 输出一个整数,表示 Alice 和 Bob 同时出现的次数。
【样例输入】 20 This is a story about Alice and Bob. Alice wants to send a private message to Bob.
【样例输出】 2
# 分析
substr (i , 3) 从位置 i 开始,长度为 3 的子串
# 代码
#include<bits/stdc++.h> | |
using namespace std; | |
const int N = 1e6 + 10; | |
bool check(char x){ | |
if(x >= 'a' && x <= 'z') return true; | |
if(x >= 'A' && x <= 'Z') return true; | |
if(x >= '0' && x <= '9') return true; | |
return false; | |
} | |
vector<int>B , b; | |
signed main(){ | |
int k ; string s; | |
cin >> k; | |
cin.get(); | |
getline(cin , s); // 整行读入字符串 | |
int n = s.size(); | |
B.push_back(-1000000000) , b.push_back(-1000000000); // 边界处理 | |
for(int i = 0 ; i < n ; i ++){ | |
if(i + 2 < n && s.substr(i , 3) == "Bob"){ | |
if(i - 1 >= 0 && check(s[i - 1]) || i + 3 < n && check(s[i + 3])) continue ; | |
B.push_back(i + 1) , b.push_back(i + 3); | |
} | |
} | |
B.push_back(1000000000) , b.push_back(1000000000); // 边界处理 | |
long long ans = 0; | |
for(int i = 0 ; i < n ; i ++){ | |
if(i + 4 < n && s.substr(i , 5) == "Alice"){ | |
if(i - 1 >= 0 && check(s[i - 1]) || i + 5 < n && check(s[i + 5])) continue ; | |
int A = i + 1 , e = i + 5; | |
// Alice 在 Bob 前面 | |
int p1 = upper_bound(B.begin() , B.end() , e + k) - B.begin() - 1; // 找到比 e+k 大的最小数的下标,那么该下标 - 1 得到的就是小于等于 e+k 的最大数的下标 | |
int p2 = lower_bound(B.begin() , B.end() , e) - B.begin(); | |
ans += p1 - p2 + 1; | |
// Alice 在 Bob 后面 | |
p1 = upper_bound(b.begin() , b.end() , A) - b.begin() - 1; // 找到比 A 大的最小数的下标,那么该下标 - 1 得到的就是小于等于 A 的最大数的下标 | |
p2 = lower_bound(b.begin() , b.end() , A - k) - b.begin(); | |
if(b[p2] > A) continue ; | |
ans += p1 - p2 + 1; | |
} | |
} | |
cout << ans << '\n'; | |
return 0; | |
} |
# 子串分值和
【问题描述】 对于一个字符串 S,我们定义 S 的分值 f (S) 为 S 中出现的不同的字符个数。例如 f (aba) = 2f (abc) = 3, f (aaa) = 1。 现在给定一个字符串 S [0...n1](长度为 n),请你计算对于所有 S 的非空子串 S [i...j](0 ⩽ i ⩽ j < n),f (S [i...j]) 的和是多少。 【输入格式】 输入一行包含一个由小写字母组成的字符串 S。 其中,1 ⩽ n ⩽ 105。
【输出格式】 输出一个整数表示答案。
【样例输入】ababc
【样例输出】 28
【评测用例规模与约定】 对于 20% 评测用例,1 ⩽ n ⩽ 10; 对于 40% 评测用例,1 ⩽ n ⩽ 100; 对于 50% 评测用例,1 ⩽ n ⩽ 1000; 对于 60% 评测用例,1 ⩽ n ⩽ 10000; 对于所有评测用例,1 ⩽ n ⩽ 100000。
# 分析
逆向思维枚举字符,计算字符能对多少子串产生贡献
# 代码
#include<bits/stdc++.h> | |
using namespace std; | |
const int N = 1e5 + 10; | |
long long ans; | |
char s[N]; | |
int suf[N] , last[30]; | |
signed main(){ | |
cin >> s + 1;// 从下标 1 开始 | |
int n = strlen(s + 1); | |
for(int j = 0 ; j <= 25 ; j ++) last[j] = n + 1; | |
for(int i = n ; i >= 1 ; i --){ | |
suf[i] = last[s[i] - 'a']; | |
last[s[i] - 'a'] = i; | |
} | |
for(int i = 1 ; i <= n ; i ++){ | |
ans += 1ll * i * (suf[i] - i); | |
} | |
cout << ans << '\n'; | |
return 0; | |
} |
# 字串排序
# 题目
给定一个常数 V ,请构造出一个只包含小写英文字母的字符串,使得该字符串满足以下 条件。 (1)冒泡排序(从小到大)的交换次数为 V 。 (2)若存在多个这样的字符串,则选择其中长度最短的。 (3)若最短的仍然存在多个,则选择其中字典序最小的。
# 分析
# 代码
#include<bits/stdc++.h> | |
using namespace std; | |
const int N = 1e2 + 10; | |
int ans, cnt[26]; | |
char s[N]; | |
signed main(){ | |
cin >> s + 1; | |
int n = strlen(s + 1); | |
for(int l = 1; l <= n; l++){ | |
for(int r = l; r <= n; r++){ | |
for(int i = 0; i <= 25; i++) cnt[i] = 0; | |
for(int i = l; i <= r; i++) cnt[s[i] - 'a']++; | |
int res = 0; | |
for(int i = 0; i <= 25; i++) if(cnt[i] > 0) res++; | |
ans += res; | |
} | |
} | |
cout << ans << '\n'; | |
return 0; | |
} |