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);
}