K题 单词的统计

K - MaratonIME goes to the karaoke 
♬ Hit me, lock me up, do anything with me, ... ♬
and Marrone, Bruno
After thousands of years repeating the title of this problem statement, always with an excited and inviting tone, Nathan finally persuaded his colleagues to go to the karaoke. He is feeling radiant with this achievement.


But there is a problem. After so much time trying to make his friends go to the karaoke, Nathan is afraid of embarrassing himself when he goes to sing the following classics of Brazilian music:


Waitress – Reginaldo Rossi
Blue Nightclub – Joaquim and Manuel
Paper Heart – Sérgio Kings
Love Bubble – Fagner
You did not teach me to forget – Fernando Mendes
To avoid the humiliation, and to not discourage his fellows in future hang outs at the karaoke, Nathan decided to print all the song’s ciphers that are available in the karaoke, to check while he sings. However, this resulted in a colossal amount of paper, that he is not able to carry.


But the perseverance and ingenuity of an envious programmer is not something you should underestimate.


Nathan realized that, after all, there were only 7 musical notes. The specialists in this matter used to represent this notes with the letters A, B, C, D, E, F and G. Even more, it’s common that the same note appears several times in sequence. He decided then, to compress the songs, changing every occurrence of repeated notes with the note followed by how many times it occurs.


For instance, given the sequence


[(A,A,A,B,B,B,C,G,G,G,G,G,G,G,G,G,G,G)] the compressed version is [A3B3C1G11]


Unfortunately, Nathan also needs to pack his floral suit and to comb his beard – two homeric jobs – and he is out of time to compress the notes. Help him to not embarrass himself by writing a program that can solve this task.


Input
Each input consist of a single line, a sequence of caracteres S such as |S| ≤ 105, formed only by the letters A, B, C, D, E, F and G.


Output
For each input, print in a single line, such as each sequence of similar notes are replaced by the note that occurs and how many times it occurs, as showed in the example.


Example
Input
ABBGA
Output
A1B2G1A1
Input
AAABBBCGGGGGGGGGGG
Output
A3B3C1G11


#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define maxn 100005
char a[maxn];
int main()
{
    int n;
    int sum;
    memset(a,0,sizeof(a));
    while(gets(a))
    {


        n = strlen(a);
        for(int i=0;i<n;i++)
        {
            sum = 1;
            if((a[i]=='C'||a[i]=='B'||a[i]=='A'||a[i]=='G')&&a[i]!=a[i+1])
            {
                 printf("%c%d",a[i],sum);
                 continue;
            }
            for(int j=i+1;j<=n;j++)
            {
                 if(a[i] == a[j])
                 {
                     sum++;
                 }
                 else
                 {
                      printf("%c%d",a[j-1],sum);
                      i=j-1;
                      break;
                 }
            }
        }
        printf("\n");
    }

}

测试样例:


### 找单词的解法分析 找单词是ACM竞赛中常见的组合优化问,主要涉及枚举和动态规划等算法思想。以下是针对目内容的详细解析及解法。 #### 目描述 给定字母A到Z的数量以及每个字母的价值(A=1, B=2, ..., Z=26),要求计算能够组成的所有单词中,价值小于等于50的单词数量。注意,单词的排列顺序无关,即ACM与CMA视为同一个单词。 #### 输入输出格式 - **输入**:第一行包含一个整数N,表示测试用例的数量。接下来N行,每行包含26个整数x1, x2, ..., x26,分别表示字母A到Z的数量。 - **输出**:对于每个测试用例,输出一行,表示满足条件的单词数量。 --- #### 解法思路 此问可以通过**状态压缩动态规划**来解决。核心思想是将每个字母及其数量作为状态的一部分,逐步构建出所有可能的单词组合,并统计其价值是否满足条件。 1. **状态定义** 定义`dp[i][j]`表示从前i种字母中选择若干个字母组成的单词,其总价值为j时的方案数。其中: - i 表示当前考虑的字母种类(从1到26)。 - j 表示单词的总价值(从0到50)。 2. **状态转移方程** 对于第i种字母,假设其数量为`xi`,价值为`vi`,则状态转移方程为: ```plaintext dp[i][j] = dp[i-1][j] + dp[i-1][j-vi] + dp[i-1][j-2*vi] + ... + dp[i-1][j-k*vi] ``` 其中,`k`为不超过`xi`且满足`j-k*vi >= 0`的最大整数。 3. **初始条件** 初始化`dp[0][0] = 1`,表示没有选择任何字母时,单词价值为0的方案数为1。 4. **最终结果** 最终答案为`sum(dp[26][j])`,其中`j`的范围是从1到50。 --- #### 实现代码 以下是基于上述思路的Python实现: ```python def count_words(test_cases): MOD = 10**9 + 7 # 防止溢出 max_value = 50 results = [] for case in test_cases: # 初始化dp数组 dp = [0] * (max_value + 1) dp[0] = 1 # 初始条件 for i in range(26): # 遍历每种字母 xi = case[i] # 当前字母的数量 vi = i + 1 # 当前字母的价值 new_dp = dp[:] # 创建一个新的dp数组 for k in range(1, xi + 1): # 枚举当前字母的选择次数 if vi * k > max_value: break for j in range(max_value, vi * k - 1, -1): new_dp[j] = (new_dp[j] + dp[j - vi * k]) % MOD dp = new_dp # 更新dp数组 # 统计总方案数 total = sum(dp[1:]) % MOD results.append(total) return results # 示例输入 if __name__ == "__main__": N = int(input()) test_cases = [] for _ in range(N): test_cases.append(list(map(int, input().split()))) result = count_words(test_cases) for r in result: print(r) ``` --- #### 复杂度分析 1. **时间复杂度** 每次处理一种字母时,需要遍历所有可能的状态(最多50个),同时枚举该字母的选取次数。因此,时间复杂度为O(26 × 50 × max(xi)),其中`max(xi)`为单个字母的最大数量。 2. **空间复杂度** 使用了一个长度为51的数组`dp`,空间复杂度为O(51)。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值