子串分值/“子串“系列I/字符贡献度/ord()与chr()

子串分值/“子串“系列I/字符贡献度/ord()与chr()_第1张图片

题解:

首先明确子串的定义:

一个字符串的非空子串是指字符串中长度至少为 1 的连续的一段字符组成的串。例如,字符串aaab 有非空子串a, b, aa, ab, aaa, aab, aaab,一共 7 个

接下来补充两个函数:

  1. ord()将字符转换成ASCII码

  1. chr()将数字代表的ASCII码转换成字符串

接下来做题:

初步思路:采用两重for循环分割出s的所有字串,再定义一个求f(s)的函数,求出答案即可,但很显然暴力是超时的

def prime(s):
  dic={}
  for temp in s:
    dic[temp]=s.count(temp)
  res=0
  for key,value in dic.items():
    if value==1:
      res+=1
  return res
s=input()
ans=1
for i in range(len(s)-1):
  for j in range(i+1,len(s)+1):
    nums=s[i:j]
    ans+=prime(nums)
    print(prime(nums),nums)
print(ans)

所以采用网上大神的思路:

题目中比较重要的信息就是 f的值仅受到在连续字串中出现一次的字符的影响。直接统计所有子串中单个字符的个数时间上过不去,那么,我们可以考虑单个字符带来的贡献度。(核心思想:换位思考
看样例:‘ababc’

我们看第二个a,虽然它可以处于多个子串中,但是如果这个子串里面还包含了其它a的话,那么这个’a’就不能对f的值产生贡献(使f的总和增加)了。而它每处于一个有效子串(除开它自己没有别的a的子串)中,f的总值就增加1。

第二个a:
在子串‘aba*‘中对f值无贡献 (*表示任意后续,可为空)
在子串’a’,‘ab’,‘abc’,‘ba’,‘bab’,'babc’中均对f值贡献了1,总共贡献6

所以,我们统计每一个字符处于多少个有效子串中即可计算出f的总和。

如何计算有效子串呢?

还是看刚刚的第二个’a’,它所处的子串要有效,就得不能包含别的‘a‘。那么我们先找到不包含其他’a’的最长子串:‘babc’

现在要做的就是找到这个串中包含’a’的连续子串的个数,如何找呢?

可以这样考虑,由于要包含’a‘,那么子串中a前面的字符选择就有:

‘b’,’’(空) 共2种情况

后面的字符选择有:

‘’(空),‘b’,‘bc’ 共3种情况

那么子串的情况就有 2×3=6种。( 即(a前面的字符个数+1) × ( a后面的字符个数+1)或 (该’a’的下标 - 上个‘a’的下标)×(下个’a’的下标 - 该’a’的下标)

要找所有a的贡献,就可以找到所有a的下标:

0,2

首尾再分别加上 -1 和 输入字符串S的长度(处理首尾的‘a’):

-1,0,2,5

三个一组,即(-1,0,2)和(0,2,5)两组。计算 (0-(-1))×(2-0)+(2-0)×(5-2)即为这两个a的贡献总值。

所以搞起来,这里我们怎么收集每个字符的位置呢,先从a到z依次判断循环,判断字母是否在字符串里,若在,依次收集它的下标,计算贡献度

import os
import sys

# 请在此输入您的代码
s=input()
node="a"
ans=0
while ord(node)<=ord("z"):
  li=[]
  if node in s:
    li.append(-1)
    for i in range(len(s)):
      if node==s[i]:
        li.append(i)
    li.append(len(s))
    for i in range(1,len(li)-1):
      ans+=(li[i]-li[i-1])*(li[i+1]-li[i])
  node=chr(ord(node)+1)
print(ans)

你可能感兴趣的:(蓝桥杯真题,算法)