題目
字符串APPAPT中包含了兩個單詞“PAT”,其中第一個PAT是第2位(P),第4位(A),第6位(T);第二個PAT是第3位(P),第4位(A),第6位(T)。
現給定字符串,問一共可以形成多少個PAT?
輸入格式:
輸入只有一行,包含一個字符串,長度不超過105
,只包含P、A、T三種字母。
輸出格式:
在一行中輸出給定字符串中包含多少個PAT。由于結果可能比較大,只輸出對1000000007取余數的結果。
輸入樣例:APPAPT
輸出樣例:2
具體內容可訪問PAT網站:題目鏈接。
算法分析
如果使用暴力破解算法,時間復雜度為O(n^3),顯然不是最優的方法。
可以使用遞推的思想來解決該問題。
已知一個長度為n的字符串中“PAT”的個數為sum,如果在這個字符串后添加一個字符后組成的新的字符串中“PAT”的個數會是多少呢?
如果添加的字符為‘P’,新字符串的“PAT”個數不發生變化。
如果添加的字符為‘A’,新字符串的“PAT”個數不發生變化。
如果添加的字符為‘T’,新字符串的“PAT”個數可能發生變化。而發生變化的數量是因為添加的‘T’構成了新的“PAT”。想要知道新構成的“PAT”的數量,則需要知道舊字符串中“PA”的數量,因為舊字符串中“PA”的數量等于新構成的“PAT”的數量。即新字符串的“PAT”個數=舊字符串中“PA”的數量+舊字符串中“PA”的數量。
想要知道舊字符串中“PA”的數量只需要使用上述的方法就可以得到,筆者就不再贅述,下文中將會用形式化方法展示算法的具體實現。
算法實現
令輸入的字符串為string,其下標為[1...n]。
string[x]為string中第x位的字母,x ∈ [1, n]。
pattern為連續的字符串模式,pattern={P, PA, PAT}。在本題中,關心的字符串模式只有上述3種。
sum(x, pattern)定義:對于子字符串string[1...x],對應字符串模式pattern的總數。其中x ∈ [0, n],且sum[0, patter] = 0。
- 當string[x] = 'T'時:
sum(x, P) <- sum(x - 1, P)
sum(x, PA) <- sum(x - 1, PA)
sum(x, PAT) <- sum(x - 1, PAT) + sum(x - 1, PA) - 當string[x] = 'A'時:
sum(x, P) <- sum(x - 1, P)
sum(x, PA) <- sum(x - 1, PA) + sum(x - 1, P)
sum(x, PAT) <- sum(x - 1, PAT) - 當string[x] = 'P'時:
sum(x, P) <- sum(x - 1, P) + 1
sum(x, PA) <- sum(x - 1, PA)
sum(x, PAT) <- sum(x - 1, PAT)
對于一個長度為n的字符串string而言,其中PAT的數量也就是sum(n, PAT)。只需要從1-n遞推地計算sum值,即可得到最終結果。因此,該算法的時間復雜度為O(n)。
代碼實現
代碼是由C++實現的,如下所示。
#include <stdio.h>
#include <string.h>
const int maxStringLength = 100100;
const int module = 1000000007;
char inputArr[maxStringLength] = {0};
int length = 0;
void getInput();
void output(long long result);
long long calcSum();
int main() {
long long result;
getInput();
if (length > 0) {
result = calcSum();
output(result);
} else {
output(0);
}
return 0;
}
void getInput() {
scanf("%s", inputArr);
length = strlen(inputArr);
}
void output(long long result) {
printf("%lld", result % module);
}
long long calcSum() {
long long sumP, sumPA, sumPAT;
sumP = sumPA = sumPAT = 0;
for (int i = 0; i < length; i ++) {
if (inputArr[i] == 'P') {
sumP ++;
} else if (inputArr[i] == 'A') {
sumPA += sumP;
} else {
sumPAT += sumPA;
}
}
return sumPAT;
}