PAT顶级题解目录
Given a string which contains only lower case English letters, how many different strings you can get after deleting AT MOST TWO characters in it?
Input Specification:
Each input file contains one test case, which gives the string whose length is in [3,106].
Output Specification:
Print in a line the number of different strings you can get after deleting at most 2 characters.
Sample Input:
ababcc
Sample Output:
15
Hint:
Deleting 0 character gets ababcc
.
Deleting 1 character gets babcc
, aabcc
, abbcc
, abacc
and ababc
.
Deleting 2 character gets abcc
, bbcc
, bacc
, babc
, aacc
, aabc
, abbc
, abac
and abab
.
题目大意:给定一个字符串,从中去除0,1,2个字符可以得到多少个不同的字符串?
解题思路:数学问题
假设给定字符串长度为N
去除0个字符串
1种
去除1个字符
若中间无连续的重复字符,应该有N种。但是中间如果存在一段连续的重复字符,长度为 n ,那么需要减去 n-1,有多段的话,同理减去即可
去除2个字符
初始有N*(N-1)/2种
①(X,X,X,X..)长度为n
对于每个单个字符Y而言,去除(X,Y)重复了,需要减去n-1
注意:这里的Y不属于重复子字符串
②(X,X,X,X)长度为m(Y,Y,Y,Y...)长度为n
对于去除(X,Y)的情况,初始计算了(m*n)种,需要减去m*n-1
③X,Y,X
去除(X,Y)和(Y,X)是相同的,减去1
Tips:本题挺容易超时的,能一遍遍历解决的不要遍历两遍,对去除2个字符的第二种情况,在存储了所有的重复子字符串长度后,通过一遍遍历计算得到的是双倍结果,再除以2,用2遍会超时。另外本题用long long int存储结果,否则第三个测试点可能会超时。
代码:
#include <bits/stdc++.h>
using namespace std;
string s;
char c = ' ';
int num = 0;
int main(){
cin >> s;
long long int ans = s.length() + 1 + ((s.length()*(s.length()-1)) >> 1), cnt = 0;
vector<int> v;
for(int i = 0; i < s.length(); ++ i){
if(s[i] != c){
if(num != 0){
v.push_back(num);
ans -= (num * (num+1)) >> 1;
cnt += num;
}
num = 0;
c = s[i];
}
else
++ num;
if(i+2 < s.length() && s[i] == s[i+2] && s[i] != s[i+1])
-- ans;
}
if(num != 0){
v.push_back(num);
ans -= (num * (num+1)) >> 1;
cnt += num;
}
ans += v.size();
ans -= cnt * (s.length() - cnt - v.size());
ans -= cnt;
long long int temp = 0;
for(long long int i = 0; i < v.size(); ++ i)
temp += (cnt - v[i] + v.size() - 1) * (v[i]+1);
printf("%lld\n", ans - temp / 2 + ((v.size()-1) * v.size())/2);
}