【codevs1099】字串变换(双端bfs)
这个题之前是用普通的bfs写出的,现在复习,觉得可以用这个练习一下双端bfs,毕竟这可是咔咔咔剪了一大堆枝呢。
这个题如果用普通bfs去求的话,唯一的难点就在于对字符串的操作,查找可以用find来做,修改则用replace。双端bfs也是差不多,只不过多加了个队列,一个存从起点跑到的点,另一个存从终点跑到的点,当发现这个点已经被跑到过了,则说明可以到达终点,如果跑完一遍所有的状态都没发现跑到之前走过的点,就说明无解。但是双端bfs要比普通的bfs不知快到哪里去了,普通的456ms,双端的则只需3ms。
ps:hash的进制数一定要开大点 ,我就说因为开太小wa了半天
#include<iostream> #include<cstring> #include<queue> #include<cstdio> const int mod=997219; using namespace std; struct in { int ceng; string s; }f,l; string a[10],b[10]; int n,ha1[mod],ha2[mod],ha3[mod],ha4[mod],ans; queue<in>qwq,qaq; inline int hash(in x) { int re=1; for(int i=0;i<x.s.length();i++) re=(re*27%mod+x.s[i]-'('+1); re%=mod; return re; } inline int hash1(in x) { int re=1; for(int i=x.s.length()-1;i>=0;i--) re=(re*27%mod+x.s[i]-'('+1); re%=mod; return re; } int bfs() { qwq.push(f),qaq.push(l); while(!qwq.empty()&&!qaq.empty()) { in owo=qwq.front(),wow=qaq.front(),x,y; for(int i=1;i<=n;i++) { for(int j=owo.s.find(a[i],0);j<owo.s.length();j=owo.s.find(a[i],j+1)) { x=owo; y.ceng=x.ceng+1; y.s=x.s.replace(j,a[i].length(),b[i]); if(y.ceng>5) return -1; if(ha2[hash(y)]&&ha4[hash1(y)]) return ha2[hash(y)]+y.ceng; qwq.push(y),ha1[hash(y)]=ha3[hash1(y)]=y.ceng; } for(int j=wow.s.find(b[i],0);j<wow.s.length();j=wow.s.find(b[i],j+1)) { x=wow; y.ceng=x.ceng+1; y.s=x.s.replace(j,b[i].length(),a[i]); if(y.ceng>5) return -1; if(ha1[hash(y)]&&ha3[hash1(y)]) return ha1[hash(y)]+y.ceng; qaq.push(y),ha2[hash(y)]=ha4[hash1(y)]=y.ceng; } } qwq.pop(),qaq.pop(); } return -1; } int main() { cin>>f.s>>l.s; n=1; while(cin>>a[n]>>b[n]) n++; n--; ans=bfs(); if(ans==-1) cout<<"NO ANSWER!"; else printf("%d",ans); }

浙公网安备 33010602011771号