5893. 【NOIP2018模擬10.4】括號序列
阿新 • • 發佈:2018-12-14
Description
Input
Output
Sample Input
輸入1: aabaab 輸入2: abcabcabc 輸入3: aabbcc
Sample Output
輸出1: 4 輸出2: 0 輸出3: 6
Data Constraint
solution
用棧儲存字母 ,只要出現相同的字母就把兩個字母都退棧,並累計方案數。
考慮列舉起點,用棧跑一次,複雜度為O()。
考慮優化。如果對於一個字首 1——>i,和另一個字首1——>j的棧相同,代表i+1——>j 的區間是一個合法區間, 因為i+1——>j 的字元都互相消完了,證明這是一個合法的區間。可以用hash記錄當前每一個字串出現的次數,然後累計答案。也可以用trie代替hash,這樣相比hash時間複雜度會大大減小。
code
1.hash版
#include<cstdio> #include<cstring> #include<map> using namespace std; #define N 1000000+200 long long st[N],d[N],pr[N],tmp[N]; long long tot,hash,ans,tw; const long long p=19260817; const long long mod=274876858367ll; map <long long,long long> Hash; int main() { freopen("bracket.in","r",stdin); freopen("bracket.out","w",stdout); long long c; st[0] = 0; pr[0] = 1; for (c = getchar(); ('a' <= c) && (c <= 'z'); c = getchar()) { st[++st[0]]=c-'a'+1; pr[st[0]]=pr[st[0]-1]*p%mod; } long long j=0; Hash[0]++; for(int i=1;i<=st[0];i++) { tmp[++tmp[0]]=st[i]; j=(j+tmp[tmp[0]]*pr[tmp[0]])%mod; if(tmp[0]>1&&tmp[tmp[0]]==tmp[tmp[0]-1]) { j=(j-tmp[tmp[0]]*pr[tmp[0]]%mod+mod-tmp[tmp[0]-1]*pr[tmp[0]-1]%mod+mod)%mod; tmp[0]-=2; } ans+=Hash[j]; Hash[j]++; } printf("%lld",ans); }
2.trie版
#include<cstdio> #include<cstring> using namespace std; #define N 1000000+200 long long ti[N],d[N],las[N],trie[N][27]; long long tot,len,cnt,x,ans; char s[N]; int main() { freopen("bracket.in","r",stdin); freopen("bracket.out","w",stdout); scanf(" %s",s+1); len=strlen(s+1); cnt=1; x=1; ti[1]++; for(long long i=1;i<=len;i++) { long long k=s[i]-'a'; if(d[tot]==k&&tot>0) { x=las[x]; ti[x]++; ans+=ti[x]-1; tot--; } else { d[++tot]=k; if(!trie[x][k]) { trie[x][k]=++cnt; las[trie[x][k]]=x; } x=trie[x][k]; ti[x]++; ans+=ti[x]-1; } } printf("%lld",ans); }