1020 Delete At Most Two Characters (35 分)(C++)

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,10​6​​].

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 babccaabccabbccabacc and ababc.

Deleting 2 character gets abccbbccbaccbabcaaccaabcabbcabac 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);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章