题目大意
有两个个字符串 a , b a,b a,b,有至多 6 6 6 个规则,可以把一个子字符串变换为另一个字符串。求至少多少次可以将 a a a 变成 b b b。
补充一下字符串的几个内置函数
string s;
s.begin()
返回字符串 s s s 第一位下标的迭代器。s.end()
返回字符串 s s s 最后一位的下一个迭代器。s.substr(pos,len)
返回从下标 p o s pos pos 开始 l e n len len 个字符构成的字符串。s.erase(pos_st,pos_nd)
删除从迭代器 p o s s t pos_{st} posst 到迭代器 p o s n d pos_{nd} posnd 之间的所有字符。
输入部分 while(cin)
cin>>a>>b;
while(cin>>s[++tot].u){
cin>>s[tot].v;
maxl=max(maxl,int(s[tot].u.length()-s[tot].v.length()));
}
tot--;
思路一:纯 dfs 暴力
#include<iostream>
#include<string>
using namespace std;
string a,b;
string u[10],v[10];
string etr;
int tot,ans=0x7fffffff;
void dfs(string now,int step){
if(now==b){
ans=min(ans,step);
return;
}
if(step>=10){
return;
}
string nown;
for(int i=1;i<=tot;i++){
int lenu=u[i].length(),lenn=now.length(),lenv=v[i].length();
for(int j=0;j+lenu-1<lenn;j++){
if(now.substr(j,lenu)==u[i]){
nown=now;
nown.erase(nown.begin()+j,nown.begin()+j+lenu);
nown=nown.substr(0,j)+v[i]+nown.substr(j,lenn-lenu-j);
dfs(nown,step+1);
}
}
}
}
int main(){
cin>>a>>b;
while(cin>>u[++tot]){
cin>>v[tot];
}
tot--;
dfs(a,0);
if(ans>=0x7fffffff) printf("NO ANSWER!");
else printf("%d",ans);
return 0;
}
60pts,TLE
思路二:
输入后对字符串从短到长排序,可以减少一部分复杂度。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string a,b;
int tot,ans=0x7fffffff,maxl=0;
struct node{
string u,v;
bool operator<(const node& tmp){
return v.length()<tmp.v.length();
}
}s[10];
inline void dfs(string now,int step){
if(now.length()>b.length()+maxl*10) return;
if(now==b){
ans=min(ans,step);
return;
}
if(step>=10 || step>=ans){
return;
}
string nown;
for(int i=1;i<=tot;i++){
int lenu=s[i].u.length(),lenn=now.length();
for(int j=0;j+lenu-1<lenn;j++){
if(now.substr(j,lenu)==s[i].u){
nown=now;
nown.erase(nown.begin()+j,nown.begin()+j+lenu);
nown=nown.substr(0,j)+s[i].v+nown.substr(j,lenn-lenu-j);
dfs(nown,step+1);
}
}
}
}
int main(){
cin>>a>>b;
while(cin>>s[++tot].u){
cin>>s[tot].v;
maxl=max(maxl,int(s[tot].u.length()-s[tot].v.length()));
}
tot--;
sort(s+1,s+tot+1);
dfs(a,0);
if(ans>=0x7fffffff) printf("NO ANSWER!");
else printf("%d",ans);
return 0;
}
80pts,TLE
思路三
最后,使用 map 对字符串去重,大大减少了从不同方式求得相同字符串而占用的时间。
给出 AC 代码
#include<iostream>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
string a,b;
int tot,ans=0x7fffffff,maxl=0;
struct node{
string u,v;
bool operator<(const node& tmp){
return v.length()<tmp.v.length();
}
}s[10];
map<string,int>mp;
void dfs(string now,int step){
if(mp[now]==1) return;
mp[now]=1;
if(now.length()>b.length()+maxl*10) return;
if(now==b){
ans=min(ans,step);
return;
}
if(step>=10 || step>=ans){
return;
}
string nown;
for(int i=1;i<=tot;i++){
int lenu=s[i].u.length(),lenn=now.length();
for(int j=0;j+lenu-1<lenn;j++){
if(now.substr(j,lenu)==s[i].u){
nown=now;
nown.erase(nown.begin()+j,nown.begin()+j+lenu);
nown=nown.substr(0,j)+s[i].v+nown.substr(j,lenn-lenu-j);
dfs(nown,step+1);
}
}
}
}
int main(){
cin>>a>>b;
while(cin>>s[++tot].u){
cin>>s[tot].v;
maxl=max(maxl,int(s[tot].u.length()-s[tot].v.length()));
}
tot--;
sort(s+1,s+tot+1);
dfs(a,0);
if(ans>=0x7fffffff) printf("NO ANSWER!");
else printf("%d",ans);
return 0;
}
100pts,AC!