码迷,mamicode.com
首页 > 其他好文 > 详细

Cryptcowgraphy

时间:2017-09-15 12:06:16      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:temp   return   bkdrhash   试验   top   elf   倒序   escape   hid   

dfs搜索+剪枝

技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 using namespace std;
  4 char fin[48];
  5 char a[80];
  6 int atop=0;
  7 char c;
  8 int cnt;
  9 int vis[1000010];
 10 struct point
 11 {
 12     char s[80];
 13     int cur;
 14 } p;
 15 int init(char *str)
 16 {
 17     int len=strlen(str);
 18     int left=0;
 19     int right;
 20     while(left<len)
 21     {
 22         while(str[left]==C||str[left]==O||str[left]==W)
 23         {
 24             left++;
 25         }
 26         if(left==atop) return 0;
 27         right=left;
 28         while(str[right]!=C&&str[right]!=O&&str[right]!=W&&str[right])
 29         {
 30             right++;
 31         }
 32         if(right-left>47) return 1;
 33         int sign=0;
 34         for(int i=0; i<48-right+left; i++)
 35         {
 36             int sign1=1;
 37             for(int j=left; j<right; j++)
 38             {
 39                 if(str[j]!=fin[i+j-left])
 40                 {
 41                     sign1=0;
 42                     break;
 43                 }
 44             }
 45             if(sign1)
 46             {
 47                 sign=1;
 48                 break;
 49             }
 50         }
 51         if(sign==0) return 1;
 52         left=right;
 53     }
 54     return 0;
 55 }
 56 unsigned int BKDRHash(char *str)
 57 {
 58     unsigned int seed = 131;
 59     unsigned int hash = 0;
 60     while (*str)
 61     {
 62         hash = hash * seed + (*str++);
 63     }
 64     return hash%1000007;
 65 }
 66 int dfs(point pp)
 67 {
 68     if(pp.cur==cnt)
 69     {
 70         if(strcmp(pp.s,fin)==0) return 1;
 71         else return 0;
 72     }
 73     int len=47+(cnt-pp.cur)*3;
 74     int c[20],o[20],w[20];
 75     int ctop=0,otop=0,wtop=0;
 76     for(int i=0; i<len; i++)
 77     {
 78         if(pp.s[i]==C) c[ctop++]=i;
 79         if(pp.s[i]==O) o[otop++]=i;
 80         if(pp.s[i]==W) w[wtop++]=i;
 81     }
 82     if(w[wtop-1]<o[otop-1]||w[wtop-1]<c[ctop-1]) return 0;
 83     if(c[0]>o[0]||c[0]>w[0]) return 0;
 84     for(int i=0;i<c[0];i++)
 85     {
 86         if(pp.s[i]!=fin[i]) return 0;
 87     }
 88     if(ctop!=otop||ctop!=wtop) return 0;
 89     if(init(pp.s)) return 0;
 90     for(int i=0; i<otop; i++)
 91     {
 92         for(int j=wtop-1; w[j]>o[i]&&j>=0; j--)
 93         {
 94             for(int k=0; c[k]<o[i]&&k<ctop; k++)
 95             {
 96                 int cwei=c[k];
 97                 int owei=o[i];
 98                 int wwei=w[j];
 99                 point p1;
100                 int p1top=0;
101                 p1.cur=pp.cur+1;
102                 for(int i=0; i<cwei; i++)
103                 {
104                     p1.s[p1top++]=pp.s[i];
105                 }
106                 for(int i=owei+1; i<wwei; i++)
107                 {
108                     p1.s[p1top++]=pp.s[i];
109                 }
110                 for(int i=cwei+1; i<owei; i++)
111                 {
112                     p1.s[p1top++]=pp.s[i];
113                 }
114                 for(int i=wwei+1; i<len; i++)
115                 {
116                     p1.s[p1top++]=pp.s[i];
117                 }
118                 p1.s[p1top]=0;
119                 int temp=BKDRHash(p1.s);
120                 if(vis[temp]==0)
121                 {
122                     vis[temp]=1;
123                     if(dfs(p1)) return 1;
124                 }
125             }
126         }
127     }
128     return 0;
129 }
130 int main()
131 {
132     memset(vis,0,sizeof(vis));
133     strcpy(fin,"Begin the Escape execution at the Break of Dawn");
134     while(scanf("%c",&c)!=EOF)
135     {
136         if(c!=\n)
137             a[atop++]=c;
138     }
139     a[atop]=0;
140     if(atop<47||(atop-47)%3)
141     {
142         printf("0 0\n");
143     }
144     else
145     {
146         cnt=(atop-47)/3;
147         strcpy(p.s,a);
148         p.cur=0;
149         if(dfs(p)) printf("1 %d\n",cnt);
150         else printf("0 0\n");
151     }
152     return 0;
153 }
View Code

剪枝: (from nocow)

  1. 由于添加的COW是一起的,因此给出的字符串的字符个数应该等于47(目标字符串的长度)+3*k。如果不满足就可直接判断无解。
  2. 除了COW三个字符外,其他的字符的个数应该和目标串相一致。如果不一致也可直接判断无解。
  3. 搜索中间肯定会出现很多相同的情况,因此需要开一个hash来记录搜索到过哪些字符串,每搜索到一个字符串,就判重。如果重复直接剪枝。这里的字符串的hash函数可以采用ELFhash,但由于ELFhash的数值太大,所以用函数值对一个大质数(我用的是99991)取余,这样可以避免hash开得太大,同时又可以减少冲突。
  4. 对搜索到的字符串,设不包含COW的最长前缀为n前缀(同样也可以定义n后缀),那么如果n前缀不等于目标串的长度相同的前缀,那么当前字符串一定无解,剪枝。N后缀也可采取相同的判断方法。
  5. 一个有解的字符串中,COW三个字母最早出现的应该是C,最后出现的应该是W,如果不满足则剪枝。
  6. 当前字符串中任意两个相邻的COW字母中间所夹的字符串一定在目标串中出现过。如果不符合可立即剪枝。
  7. 需要优化搜索顺序。经过试验我们可以发现,O的位置对于整个COW至关重要。可以说,O的位置决定了整个串是否会有解。因此,我们在搜索时,应该先枚举O的位置,然后再枚举C和W的位置。其中W要倒序枚举。这样比依次枚举COW至少要快20~30倍。
  8. 在判断当前串的子串是否包含在目标串中的时候,可以先做一个预处理:记录每一个字母曾经出现过的位置,然后可以直接枚举子串的第一个字母的位置。这样比用pos要快2倍左右。

Cryptcowgraphy

标签:temp   return   bkdrhash   试验   top   elf   倒序   escape   hid   

原文地址:http://www.cnblogs.com/abc3288288351/p/7525336.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!