其他分享
首页 > 其他分享> > 2868. 子串分值

2868. 子串分值

作者:互联网

题目链接

2868. 子串分值

对于一个字符串 \(S\) ,我们定义 \(S\) 的分值 \(f(S)\) 为 \(S\) 中恰好出现一次的字符个数。
例如 \(f(" a b a ")=1 , f(" a b c ")=3, f(" a a a ")=0\) 。
现在给定一个字符串 \(S[0 \ldots n-1]\) (长度为 \(n\) ),请你计算对于所有 \(S\) 的非空子串 \(S[i \ldots j](0 \leq i \leq j<n), f(S[i \ldots j])\) 的和是多少。

输入格式

输入一行包含一个由小写字母组成的字符串 \(S\) 。

输出格式

输出一个整数表示答案。

数据范围

对于 \(20 \%\) 的评测用例, \(1 \leq n \leq 10\) ;
对于 \(40 \%\) 的评测用例, \(1 \leq n \leq 100\) ;
对于 \(50 \%\) 的评测用例, \(1 \leq n \leq 1000\) ;
对于 \(60 \%\) 的评测用例, \(1 \leq n \leq 10000\) ;
对于所有评测用例, \(1 \leq n \leq 100000\) 。

输入样例:

ababc

输出样例:

21

样例说明

所有子串 \(f\) 值如下:

a     1
ab    2
aba   1
abab  0
ababc 1
 b    1
 ba   2
 bab  1
 babc 2
  a   1
  ab  2
  abc 3
   b  1
   bc 2
    c 1

解题思路

思维

考虑每一位对答案的贡献,先复制上一位对答案的贡献,针对上一位加入当前字符后产生的贡献:当这一位作为单个字符时,其产生的贡献为当前位与前面出现该字符的距离,如果前一位产生的贡献中有当前字符,则当前字符到前一位字符的距离产生的贡献不变,同时要减去与当前字符相同的前一位产生的贡献,同时如果前一位的前面不止一个当前字符,要加上与当前字符相同的前前位的贡献以消除之前减去的贡献

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define help {cin.tie(NULL);cout.tie(NULL);}
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
template <typename T> bool chkMax(T &x,T y){return (x<y?x=y,1:0);}
template <typename T> bool chkMin(T &x,T y){return (x>y?x=y,1:0);}


template <typename T> inline void read(T &x)
{
	int f=1;x=0;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();
	}
	while(s>='0'&&s<='9'){x+=x*10+(s^48),s=getchar();
	}
	x*=f;
}

string s;
int p[26],lp[26],cnt[26];
int main()
{
	cin>>s;
	int n=s.size();
	s=' '+s;
	LL res=0;
	int lst=0;
	for(int i=1;i<=n;i++)
	{
		int t=s[i]-'a';	
		lst+=i-p[t];
		if(p[t])lst=lst-p[t]+lp[t];
		res+=lst;
		lp[t]=p[t];
		p[t]=i;
	}
	cout<<res;
	return 0;
}

标签:子串,字符,评测,leq,2868,分值,贡献,用例,int
来源: https://www.cnblogs.com/zyyun/p/16027383.html