奶牛加密术
描述
农民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 }