PAT-B-1040
1040 有几个PAT(25 分)
字符串 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
思路:
首先暴力破解没错,但O(n^3)的时间复杂度不能接受。
求PAT个数,可以分析为找A的位置,找到A之后看A前面有几个P(count_P),再看A后面有几个T(count_T),该位置的A参与的有效“PAT”个数即:count_P * count_T,循环找A,并计算结果,最后求余。
可以先使用循环计算从0到当前位置有多少P,从len-1到当前位置有多少T,然后在找A的循环找就可以在O(1)下得到当前位置之前的P的个数、之后T的个数。
时间复杂度:O(3N),空间复杂度O(3N)。
卡在测试项4没能过,问题见36行备注。
1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAXSIZE 1000000007 5 6 typedef long ElementType; 7 8 int main(void){ 9 int i, A_Index=0; 10 ElementType count=0; 11 char str[100001]; 12 13 gets(str); 14 int len = strlen(str); 15 int Count_T[len], Count_P[len], A_Pos[len]; 16 17 Count_P[0] = str[0] == 'P'? 1 : 0; 18 Count_T[len-1] = str[len-1] == 'T'? 1 : 0; 19 for( i=1; i<len; i++) 20 if( str[i] == 'P' ) 21 Count_P[i] = Count_P[i-1]+1; 22 else{ 23 Count_P[i] = Count_P[i-1]; 24 if( str[i] == 'A' ) 25 A_Pos[A_Index++] = i; 26 } 27 28 for( i=len-2; i>=0; i--) 29 if( str[i] == 'T' ) 30 Count_T[i] = Count_T[i+1]+1; 31 else 32 Count_T[i] = Count_T[i+1]; 33 34 for( i=0; i<A_Index; i++){ 35 count += Count_P[A_Pos[i]] * Count_T[A_Pos[i]]; 36 while(count >= MAXSIZE)//这里只能是while不能用if 37 count -= MAXSIZE; 38 } 39 40 printf("%ld", count); 41 42 return 0; 43 }
看到一个更加简明的方法,整体复杂度还是O(2n), 大约少了一个O(N)的时间, 且代码更短,占用空间O(1)。参考出处
1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAXSIZE 1000000007 5 6 typedef long ElementType; 7 8 int main(void){ 9 int i, count_P=0, count_A=0, count_T=0; 10 ElementType count=0; 11 char str[100001]; 12 13 gets(str); 14 15 for( i=0; str[i]; ++i) 16 if( str[i] == 'T' ) 17 count_T++; 18 19 for( i=0; str[i]; ++i){ 20 if( str[i] == 'P' ) 21 count_P++; 22 else if( str[i] == 'T') 23 count_T--; 24 else if( str[i] == 'A' ) 25 count = ( count+ (count_P*count_T) % MAXSIZE ) % MAXSIZE; 26 } 27 28 printf("%ld", count); 29 30 return 0; 31 }