自学内容网 自学内容网

每日OJ题_牛客_DP36 abb_C++_Java

目录

牛客_DP36 abb

题目解析

C++代码1暴力

C++代码2DP

Java代码


牛客_DP36 abb

abb_牛客题霸_牛客网

描述:

leafee 最近爱上了 abb 型语句,比如“叠词词”、“恶心心”

leafee 拿到了一个只含有小写字母的字符串,她想知道有多少个 "abb" 型的子序列?
定义: abb 型字符串满足以下条件:

  1. 字符串长度为 3 。
  2. 字符串后两位相同。
  3. 字符串前两位不同。

输入描述:

第一行一个正整数 n

第二行一个长度为 n 的字符串(只包含小写字母)

1≤n≤10^5

输出描述:

"abb" 型的子序列个数。


题目解析

        用abb中第一个出现的b来考虑,一个字符作为第一b能产生的abb字符,等于它后面相同的字符数量(意味着还能凑成多少个bb)乘以它前面与它不相同的字符数量(可以被当作a的)。于是先记录每一个字符总出现的次数。然后再遍历字符串记录每个字符已经出现的次数和后面还没出现的次数。

C++代码1暴力

暴力代码:(也就时间复杂度也就O(26N))

#include <iostream>
#include <vector>
using namespace std;

int main() // 滑动窗口?不是
{
    int n = 0;
    string str;
    cin >> n >> str;
    vector<int> arr(26);
    for(int i = 0; i < n; ++i)
    {
        arr[str[i] - 'a']++;
    }
        // for(int j = 0; j < 26; ++j)
        // {
        //     cout << arr[j] << " ";
        // }
    long long ret = 0;
    for(int i = 0; i < n; ++i) // 计算str[i]右边有多少个其它字符
    {
        for(int j = 0; j < 26; ++j)
        {
            if(str[i] - 'a' != j && arr[j] >= 2)
            {
                // int cnt = 0; // 用下面的的等差数列求和公式求
                // for(int k = arr[j] - 1; k >= 1; --k)
                // {
                //     cnt += k;
                // }
                // ret += cnt;

                // 等差数列求和公式:n * (a1 + an) / 2
                ret += (arr[j] - 1) * (1 + arr[j] - 1) / 2; // 求组合数C n 2?
            }
        }
        // cout << ret << " " << str[i] << " " <<  arr[str[i] - 'a'] << endl; // debug
        arr[str[i] - 'a']--;
    }
    cout << ret;
    return 0;
}
/*
3个c 3, 4个c 6
7
abcbccc // 6个acc n个c (n-1)!, 3+2+1
8
abcbcccc // 24个acc 5个c (n-1)!, 4+3+2
*/

C++代码2DP

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int n = 0;
    string str;
    cin >> n >> str;
    vector<int> arr(26);
    for(int i = 0; i < n; ++i)
    {
        arr[str[i] - 'a']++;
    }
        // for(int j = 0; j < 26; ++j)
        // {
        //     cout << arr[j] << " ";
        // }
    long long ret = 0;
    for(int i = 0; i < n; ++i) // 计算str[i]右边有多少个其它字符
    {
        for(int j = 0; j < 26; ++j)
        {
            if(str[i] - 'a' != j && arr[j] >= 2)
            {
                int cnt = 0;
                for(int k = arr[j] - 1; k >= 1; --k)
                {
                    cnt += k;
                }
                ret += cnt;
            }
        }
        // cout << ret << " " << str[i] << " " <<  arr[str[i] - 'a'] << endl; // debug
        arr[str[i] - 'a']--;
    }
    cout << ret;
    return 0;
}
/*
3个c 3, 4个c 6
7
abcbccc // 6个acc n个c (n-1)!, 3+2+1
8
abcbcccc // 24个acc 5个c (n-1)!, 4+3+2
*/

Java代码

import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main
{
    public static void main(String[] args) 
    {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        char[] s = in.next().toCharArray();
        long[] f = new long[26];
        long[] g = new long[26];
        long ret = 0;
        for(int i = 0; i < n; i++)
        {
            int x = s[i] - 'a';
            ret += f[x];
            // 更新哈希表
            f[x] = f[x] + i - g[x];
            g[x] = g[x] + 1;
        }
        System.out.println(ret);
    }
}

原文地址:https://blog.csdn.net/GRrtx/article/details/143800664

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!