1215:Co-occurrence Search
問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1215
文字列といくつかの文字が与えられる。
文字をすべて含む、文字列の部分列の中で最小の長さのものの個数と、そのような部分列のなかで最初に現れるものを出力せよ。
尺取り法のようなことをした。
#include<iostream> #include<vector> #include<algorithm> #include<string> #define INF (1<<29) #define all(c) (c).begin(),(c).end() using namespace std; int main(void){ string s,t,in; while(true){ s.clear(); t.clear(); while(true){ getline(cin,in); if(in.size()==0)break; s+=in; } while(true){ getline(cin,in); if(in.size()==0)break; t+=in; } if(s.size()==0 && t.size()==0)break; int sl=s.size(),tl=t.size(); int now[tl],ans=0; string res=""; fill(now,now+tl,INF); int tmp=0; for(int i=0;i<sl;i++){ for(int j=0;j<tl;j++){ if(s[i]==t[j]){ now[j]=min(now[j],i); } } } bool flag=false; for(int i=0;i<tl;i++){ flag|=(now[i]>=INF); } if(flag){ cout << 0 << endl << endl;; continue; } int left=INF,right=-1,lid,rid; for(int i=0;i<tl;i++){ if(left>now[i])left=now[i],lid=i; if(right<now[i])right=now[i],rid=i; } ans++; res=s.substr(left,right-left+1); while(true){ int mn=INF,id=0; for(int i=0;i<tl;i++){ if(mn>now[i])mn=now[i],id=i; } while(now[id]<sl && s[++now[id]]!=t[id]); if(s[now[id]]!=t[id])break; int l=INF,r=0; bool fg=true; for(int i=0;i<tl;i++){ l=min(l,now[i]); r=max(r,now[i]); fg&=(now[i]>=sl-1); } if(fg)break; if(res.size()>r-l+1){ ans=0; res=s.substr(l,r-l+1); } if(res.size()==r-l+1)ans++; } cout << ans << endl << endl; for(int i=0;i<res.size();i++){ cout << res[i]; if((i+1)%72==0)cout << endl; } if(res.size()%72>0)cout << endl; cout << endl; } return 0; }