奶牛加密术

描述

农民Brown和John的牛们计划协同逃出它们各自的农场。它们设计了一种加密方法用来保护它们的通讯不被他人知道。
如果一头牛有信息要加密,比如"International Olympiad in Informatics",它会随机地把C,O,W三个字母插到到信息中(其中C在O前面,O在W前面),然后它把C与O之间的文字和 O与W之间的文字的位置换过来。这里是两个例子:
International Olympiad in Informatics -> CnOIWternational Olympiad in Informatics
International Olympiad in Informatics -> International Cin InformaticsOOlympiad W
为了使解密更复杂,牛们会在一条消息里多次采用这个加密方法(把上次加密的结果再进行加密)。一天夜里,John的牛们收到了一条经过多次加密的信息。请你写一个程序判断它是不是这条信息经过加密(或没有加密)而得到的:
Begin the Escape execution at the Break of Dawn

格式

输入格式

一行,不超过75个字符的加密过的信息。

输出格式

一行,两个整数. 如果能解密成上面那条逃跑的信息,第一个整数应当为1,否则为0;如果第一个数为1,则第二个数表示此信息被加密的次数,否则第二个数为0。

样例1

样例输入1

Begin the EscCution at the BreOape execWak of Dawn

样例输出1

1 1



搜索每个COM对,逆向恢复
1.剪枝一 每个C和C、O、M,O和C、O、M,M和
C、O、M之间的字符串都应该在原串中出现
2.剪枝二 字符串开头到第一个C之间的字符串应该和原串的前缀一样,同理后缀也一样
3.剪枝三 先搜索O,再搜索C,再逆序搜索M
4.剪枝四 避免重复搜索,HASH

只使用1,2,3剪枝可以过7个点,剪枝4很重要
 1 #include<iostream>
 2 #include<string>
 3 #define N 99991
 4 using namespace std;
 5 string tool="Begin the Escape execution at the Break of Dawn";
 6 bool h[N]={0};
 7 
 8 bool compare(int x,int y,string s){
 9      int j;
10      for(int i=0;i<tool.size()-(y-x);++i)
11      {
12         for(j=x;j<=y;++j)
13         if(s[j]!=tool[i+j-x]) break;
14         if(j>y) return true;     
15              }
16      return false;
17      }
18 
19 int ELFhash(string s){
20 
21     unsigned long h=0;
22     unsigned long x=0;
23     int i=0;
24     while(i<s.size())
25     {
26         h=(h<<4)+s[i];i++;  //h左移4位,当前字符ASCII存入h的低四位
27                 if( (x=h & 0xF0000000L)!=0)
28         { //如果最高位不为0,则说明字符多余7个,如果不处理,再加第九个字符时,第一个字符会被移出
29           //因此要有如下处理
30           h^=(x>>24);
31           //清空28~31位
32           h&=~x;
33         }
34     }
35     return h % N;
36 }
37 
38 bool search(int ans,string s){
39     //剪枝4
40      if(h[ELFhash(s)]==true) return false;
41    //剪枝2
42      int i=0,j=0;
43      for(i=0;i<s.size();++i)
44      if(s[i]=='C') break;
45      if(i>0&&s.substr(0,i)!=tool.substr(0,i)) return false;
46      for(j=1;j<s.size();++j)
47      if(s[s.size()-j]=='W') break;
48      if(j!=1&&s.substr(s.size()-j+1,j-1)!=tool.substr(tool.size()-j+1,j-1)) return false;
49      
50   //剪枝1     
51      i=0;j=0;
52      while(j<s.size())
53      {
54         while(i<s.size()&&(s[i]=='C'||s[i]=='O'||s[i]=='W')) i++;
55         j=i;
56         while(j<s.size()&&s[j]!='C'&&s[j]!='O'&&s[j]!='W') j++;
57         if(j-1>=i)
58         {if(!compare(i,j-1,s)) return false;}              
59         j++;i=j;              
60                       }
61      
62      if(s=="Begin the Escape execution at the Break of Dawn") {cout<<1<<" "<<ans<<endl;return true;}
63      
64    //剪枝3
65      for(int j=0;j<s.size();++j)
66      if(s[j]=='O')
67      for(int i=0;i<j;++i)
68      if(s[i]=='C')
69      for(int k=s.size()-1;k>j;--k)
70      if(s[k]=='W')
71      {
72        if(search(ans+1,s.substr(0,i)+s.substr(j+1,k-j-1)+s.substr(i+1,j-i-1)+s.substr(k+1,s.size()-k-1))) return true;
73        else h[ELFhash(s.substr(0,i)+s.substr(j+1,k-j-1)+s.substr(i+1,j-i-1)+s.substr(k+1,s.size()-k-1))]=true;
74                   
75                   }
76      
77      
78      return false;
79      
80      }
81 
82 
83 int main()
84 { 
85     string s;
86     getline(cin, s);
87     if(!search(0,s)) cout<<0<<" "<<0<<endl;
88 
89   //  system("pause");
90 
91     } 

 

 
posted on 2017-11-17 20:30  怡红公子  阅读(358)  评论(0编辑  收藏  举报