問題はこちら
No.457 (^^*) - yukicoder
・O(|S|^3)
各カッコ対に対して、その間に'^^*'があるかどうか判定する
当然TLE
・O(|S|^2)
各'('について、そこから右に見て'^^*'があった以降にある')'の数を数える
(*^^)も同様
17/01/31修正
char s[10010];i,j,L,R; int main(){ gets(s); for(i=0;s[i];i++)if(s[i]=='('){ //(^^*) j=i; while(s[j]!='\0'&&s[++j]!='^'); while(s[j]!='\0'&&s[++j]!='^'); while(s[j]!='\0'&&s[++j]!='*'); while(s[j]!='\0'){ if(s[j]==')')L++; j++; } //(*^^) j=i; while(s[j]!='\0'&&s[++j]!='*'); while(s[j]!='\0'&&s[++j]!='^'); while(s[j]!='\0'&&s[++j]!='^'); while(s[j]!='\0'){ if(s[j]==')')R++; j++; } } printf("%d %d",L,R); return 0; }
・O(|S|)
よく考えれば上でやったことをDPにすればO(|S|)だった。
左から順に見ていって ( , (^ , (^^ , (^^* ,(^^*) が各々いくつあるかを覚える
右も同様
int main(){ int i,dpL[5]={},dpR[5]={}; char s[10010]; gets(s); for(i=0;s[i];i++){ switch(s[i]){ case '(': dpL[0]++; dpR[0]++; break; case '^': dpL[2]+=dpL[1];dpL[1]=dpL[0];dpL[0]=0; dpR[3]+=dpR[2];dpR[2]=dpR[1];dpR[1]=0; break; case '*': dpL[3]+=dpL[2];dpL[2]=0; dpR[1]+=dpR[0];dpR[0]=0; break; case ')': dpL[4]+=dpL[3]; dpR[4]+=dpR[3]; } } printf("%d %d",dpL[4],dpR[4]); return 0; }
とりあえずゴルフした限りではO(|S|^2)の方が短くなった
・O(|S|)
超素直に
i,d[10]; main(){ for(;read(0,&i,1);) //')'のとき i&1?d[4]+=d[3],d[9]+=d[8]: //'^'のとき i&4?d[2]+=d[1],d[1]=*d,*d=0,d[8]+=d[7],d[7]=d[6],d[6]=0: //'('のとき ~i&2?++*d,d[5]++: //'*'のとき i>11?d[3]+=d[2],d[2]=0,d[6]+=d[5],d[5]=0: 0; i=!printf("%d %d",d[4],d[9]); }
206B
・O(|S|^2)
まずざっくりと。
tL,tRで状態を保存して遷移をチェックする
char s['~~'];i,j,L,R,tL,tR; main(){ for(gets(s);s[i];tL=tR=0,i++)for(j=i;s[++j];)if(s[i]=='('){ tL<2&s[j]=='^'|tL==2&s[j]=='*'?++tL:s[j]==')'?tL+=tL>2,L+=tL>3:0; tR<3&tR>0&s[j]=='^'|!tR&s[j]=='*'?++tR:s[j]==')'?tR+=tR>2,R+=tR>3:0; } i=!printf("%d %d",L,R); }
これをぎゅっとする
'^'が94、'*'が42、'('が40、')'が41
tL<2&s[j]=='^'|tL==2&s[j]=='*'?++tL:s[j]==')'?tL+=tL>2,L+=tL>3:0; tL>1|s[j]-94&&tL-2|s[j]%7:s[j]==')'&&tL>2?L+=++tL>3:0:++tL; tL>1|s[j]-94&&tL-2|s[j]%7:s[j]&tL>2?L+=++tL>3:0:++tL; if(s[i]=='(')tL>1|s[j]-94&&tL-2|s[j]%7:s[j]&tL>2?L+=++tL>3:0:++tL; tL>1|s[j]-94&&tL-2|s[j]%7:s[j]&tL>2?L+=++tL>3:0:s[i]%8||++tL;
ということでループ圧縮も一緒にして
#define f(X,Y,Z,W)X|s[j]-94&&Y|s[j]%7?s[j]&Z>2?W+=++Z>3:0:s[i]%8||++Z, char s['~~']; i,j,p,q,L,R; main(){ for(gets(s);s[++j]?f(p>1,p-2,p,L)f(q-1&q-2,q,q,R)1:(p=q=0,s[j=++i]);); i=!printf("%d %d",L,R); }
197B
17/07/15追記
頑張るとO(|S|)解の方が短くなった。
条件分岐を見直し、defineを有効活用した
#define f(n)d[n]+=d[n-1], d[]; main(i){ for(;read(0,&i,1);) //')'のとき i&1?f(4)f(9)0: //'^'のとき i&4?f(2)d[1]=*d,*d=0,f(8)d[7]=d[6],d[6]=0: //'*'のとき('\n'もここに) i&2?f(3)d[2]=0,f(6)d[5]=0: //'('のとき ++*d+d[5]++; printf("%d %d",d[4],d[9]); }
178B