洛谷 P1032 字串变换

P1032 字串变换

题目描述

已知有两个字串 A,BA,B 及一组字串变换的规则(至多 66 个规则):

A_1A1 -> B_1B1

A_2A2 -> B_2B2

规则的含义为:在 AA 中的子串 A_1A1 可以变换为 B_1B1 , A_2A2 可以变换为 B_2B2 …。

例如: AA =' abcdabcd ' BB =' xyzxyz '

变换规则为:

‘ abcabc ’->‘ xuxu ’‘ udud ’->‘ yy ’‘ yy ’->‘ yzyz ’

则此时, AA 可以经过一系列的变换变为 BB ,其变换的过程为:

‘ abcdabcd ’->‘ xudxud ’->‘ xyxy ’->‘ xyzxyz ’

共进行了 33 次变换,使得 AA 变换为 BB 。

输入输出格式

输入格式:

 

输入格式如下:

ABB
A_1A1 B_1B1
A_2A2 B_2B2 |-> 变换规则

... ... /

所有字符串长度的上限为 2020 。

 

输出格式:

 

输出至屏幕。格式如下:

若在 1010 步(包含 1010 步)以内能将 AA 变换为 BB ,则输出最少的变换步数;否则输出"NO ANSWER!"

 

输入输出样例

输入样例#1: 复制
abcd xyz
abc xu
ud y
y yz
输出样例#1: 复制
3
思路:深搜60TLE,宽搜AC.
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100000
using namespace std;
int n=1,ans=0x7f7f7f7f;
string A,B;
int net[MAXN],vis[MAXN];
struct nond{
    string s1,s2;
}v[7];
int judge(string sa,string sb){
    int len1=sa.length();
    if(len1!=sb.length())    return 0;
    else for(int i=0;i<len1;i++)
        if(sa[i]!=sb[i])    return 0;
    return 1;
}
void getnet(string p){
    int plen=p.length();
    net[0]=-1;
    int k=-1;
    int j=0;
    while(j<plen){
        if(k==-1||p[j]==p[k]){
            j++;k++;
            net[j]=k;
        }
        else k=net[k];
    }
}
int kmp(string s,string p){
    getnet(p);
    int i=0,j=0;
    int slen=s.length();
    int plen=p.length();
    while(i<slen){
        if(j==-1||s[i]==p[j]){
            i++;j++;
        }
        else    j=net[j];
        if(j==plen){
            return i-plen;
            j=0,i--;
        }
    }
    return -1;
}
void dfs(int tot,string s){
    if(tot==10)    return ;
    if(judge(s,B)==1){
        ans=min(ans,tot);
        return ;
    }
    for(int i=1;i<=n;i++)
        if(vis[i]<=2){
            //memset(net,0,sizeof(net));
            int l1=s.length(),l2=v[i].s1.length();
            int be=kmp(s,v[i].s1);
            if(be!=-1){
                string s3;vis[i]++;
                for(int j=0;j<be;j++)    s3+=s[j];
                s3+=v[i].s2;
                for(int j=be+l2;j<l1;j++)    s3+=s[j];
                dfs(tot+1,s3);vis[i]--;
            }
        }
}
int main(){
    cin>>A>>B;
    while(cin>>v[n].s1>>v[n].s2){
        n++;
        if(n==7)    break; 
    } 
    n--;
    dfs(0,A);
    if(ans==0x7f7f7f7f)    cout<<"NO ANSWER!"<<endl;
    else cout<<ans;
}
60分暴力
#include<map>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm> 
#define maxn 15
using namespace std;
struct node{
    string str;
    int step;
};
string a,b;
string orginal[maxn];
string translated[maxn];
int n,ans;
map<string,int>ma;
string trans(const string &str,int i,int j){
    string ans="";
    if(i+orginal[j].length()>str.length())
        return ans;
    for (int k=0;k<orginal[j].length();k++)
        if (str[i+k]!=orginal[j][k])
            return ans;
    ans=str.substr(0,i);
    ans+=translated[j];
    ans+=str.substr(i+orginal[j].length());
    return ans;
}
void bfs(){
    queue<node>q;
    node s;
    s.str=a;
    s.step=0;
    q.push(s);
    while(!q.empty()){
        node u=q.front();
        q.pop();
        string temp;
        if(ma.count(u.str) == 1)    continue;
        if(u.str==b){
            ans=u.step;
            break;
        }
        ma[u.str] = 1;
        for (int i=0;i<u.str.length();i++)
            for (int j=0;j<n;j++){
                temp=trans(u.str,i,j);
                if(temp!=""){
                    node v;
                    v.str=temp;
                    v.step=u.step+1;
                    q.push(v);
                }
            }
    }
    if(ans>10||ans==0)    cout<<"NO ANSWER!"<<endl;
    else    cout<<ans<<endl;
}
int main(){
    cin>>a>>b;
    while(cin>>orginal[n]>>translated[n])    n++;
    bfs();
    return 0;
}
View Code
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/9341768.html