1. 程式人生 > >「NOIP2002」「Codevs1099」 字串變換

「NOIP2002」「Codevs1099」 字串變換

但是 字母 下標 ref desc 相關 put -c 系列

1099 字串變換

2002年NOIP全國聯賽提高組

時間限制: 1 s 空間限制: 128000 KB 題目等級 : 黃金 Gold 題目描述 Description

已知有兩個字串 $A$, $B$ 及一組字串變換的規則(至多6個規則):
     $A1$ -> $B1$
     $A2$ -> $B2$
  規則的含義為:在$ A$中的子串 $A1$ 可以變換為 $B1$、$A2$ 可以變換為 $B2$ …。
    例如:$A=‘abcd‘ B=‘xyz‘$
  變換規則為:

    $‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’$

  則此時,$A$ 可以經過一系列的變換變為 $B$,其變換的過程為:
   $‘abcd’->‘xud’->‘xy’->‘xyz’$

  共進行了三次變換,使得 $A$ 變換為$B$。

輸入描述 Input Description

輸入格式如下:

   $A$ $B$
   $A1$ $B1$ \
   $A2$ $B2$ |-> 變換規則
   ... ... /
  所有字符串長度的上限為 20。

輸出描述 Output Description

若在 10 步(包含 10步)以內能將 $A$ 變換為 $B$ ,則輸出最少的變換步數;否則輸出"NO ANSWER!"

樣例輸入 Sample Input

abcd xyz
abc xu
ud y
y yz

樣例輸出 Sample Output

3

數據範圍及提示 Data Size & Hint

hehe


題解

教材(來自Luogu的題解

這種字符串變換都是考STL的使用啊!!!QAQ

前置知識:

1.map入門:

定義:
    map<type1,type2>mp;
    相當於一個用type1當下標的數組。
 eg:
    map<double,int>mp;
    mp[2.6]=3;
    cout<<mp[2.6];
    //輸出3

查找:
直接向數組一樣訪問就行了,但是要先問一下是否存在。
if(mp.find(x)==mp.end())表示這個下標沒有存過。

然後map的各種操作應該(應該?)都是O(log)的。

2.string相關:

定義:
    string a;
    //可以定義字符串數組

訪問其中下標為i的字母:
    int k=a[i];
    //註意是從0開始排的

在string a裏面找子串b
    int pos=a.find(b);
    //如果存在子串b 返回b的第一個字符對應在a裏面的下標(若有多個匹配,返回第一個匹配的下標) 否則返回-1

(劃重點)
把string a從pos開始長l的字符整體換成字串b
    a.replace(pos,l+1,b);
    //stl的區間都是左開右閉的

然後就可以亂搞了,BFS一下就星。

這個st.replace可以再神奇一點嗎?!!!!!

 1 /*
 2     qwerta
 3     P1032 字串變換
 4     Accepted
 5     100
 6     代碼 C++,1.14KB
 7     提交時間 2018-09-26 19:13:29
 8     耗時/內存
 9     26ms, 1432KB
10 */
11 #include<iostream>
12 #include<cstring>
13 #include<cstdio>
14 #include<queue>
15 #include<map>
16 using namespace std;
17 string a[13],b[13];
18 string ma,mb;
19 queue<string>qs;//存字符串
20 queue<int>qn;//存對應的轉換次數
21 int n=1;
22 map<string,int>m;
23 int bfs()
24 {
25     qs.push(ma);//push初始狀態
26     qn.push(0);
27     while(!qs.empty()&&qn.front()<10)//如果有的搜並且次數不超過10
28     {
29         int d=qn.front();
30         string s=qs.front();
31         if(m.find(s)==m.end())//如果s在map中沒有被記錄過
32         {
33             m[s]=1;//mark一下
34             for(int c=1;c<=n;++c)//枚舉六種變換
35             {
36                 s=qs.front();
37                 while((s.find(a[c]))!=-1)//如果找得到子串a[c]
38                 {
39                     string ss=qs.front();//搞一個輔助的ss
40                     int pos=s.find(a[c]);
41                     ss.replace(pos,a[c].size(),b[c]);//把ss替換一下
42                     if(ss==mb)return d+1;//找到了就return
43                     qs.push(ss);
44                     qn.push(d+1);//push當前的收獲
45                     s[pos]=*;//把s的這一位換成無關字符,這樣下一次就會自動搜下一位了
46                 }
47             }
48         }
49         qs.pop();qn.pop();
50     }
51     return -1;//搜完了還沒搜到則無解
52 }
53 int main()
54 {
55     //freopen("a.in","r",stdin);
56     ios::sync_with_stdio(false);
57     cin.tie(false),cout.tie(false);//cin好伴侶(據說能快過scanf
58     cin>>ma>>mb;
59     while(cin>>a[n]>>b[n])n++;
60     n--;
61     int k=bfs();
62     if(k==-1){cout<<"NO ANSWER!";}
63     else cout<<k;
64     return 0;
65 }


不用map判重也不會TLE 差評

不用map:
/*
    qwerta
    P1032 字串變換
    Accepted
    100
    代碼 C++,1.14KB
    提交時間 2018-09-26 19:14:03
    耗時/內存
    389ms, 64472KB
*/
//(摔

「NOIP2002」「Codevs1099」 字串變換