[JSOI2009]电子字典 hash

题面:洛谷

题解:

  做法。。。。非常暴力。

  因为要求的编辑距离最多只有1,所以我们直接枚举对那个位置(字符)进行操作,进行什么样的操作,加入/修改/删除哪个字符,然后暴力枚举hash判断即可,

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define R register int
  4 #define AC 25
  5 #define ac 10100
  6 #define base 26
  7 #define LL long long
  8 #define us unsigned
  9 
 10 int n, m, len, ans, cnt, dfn;
 11 int id[ac];
 12 us LL hs[ac], qw[AC], ls[AC], rs[AC];
 13 char s[AC];
 14 
 15 void build()
 16 {
 17     scanf("%s", s + 1), len = strlen(s + 1), ++ cnt;
 18     for(R i = 1; i <= len; i ++) hs[cnt] = hs[cnt] * base + s[i];
 19 }
 20 
 21 void pre()
 22 {
 23     scanf("%d%d", &n, &m);
 24     for(R i = 1; i <= n; i ++) build();
 25     sort(hs + 1, hs + n + 1);
 26     qw[0] = 1;
 27     for(R i = 1; i <= 20; i ++) qw[i] = qw[i - 1] * base;
 28 }
 29 
 30 bool half(us LL x)
 31 {
 32     int l = 1, r = n, mid;
 33     while(l < r)
 34     {
 35         mid = (l + r) >> 1;
 36         if(hs[mid] == x) 
 37         {
 38             if(id[mid] == dfn) return false;
 39             id[mid] = dfn; return true;
 40         }
 41         else if(hs[mid] < x) l = mid + 1;
 42         else r = mid - 1;
 43     }
 44     if(hs[l] != x) return false;
 45     if(id[l] == dfn) return false;
 46     id[l] = dfn; return true;
 47 }
 48 
 49 bool check()
 50 {
 51     scanf("%s", s + 1), len = strlen(s + 1), ans = 0, ++ dfn;
 52     us LL x = 0;
 53     memset(rs, 0, sizeof(rs));//why?????大概是因为下面判断的时候可能用到r[len + 1]吧,而r[len + 1]应该要=0的
 54     for(R i = 1; i <= len; i ++) x = x * base + s[i];
 55     if(half(x))
 56     {
 57         printf("-1\n");
 58         return true;
 59     }
 60     for(R i = 1; i <= len; i ++) ls[i] = ls[i - 1] * base + s[i];
 61     for(R i = 1; i <= len; i ++) rs[i] = ls[len] - ls[i - 1] * qw[len - i + 1];
 62     //for(R i = 1; i <= len; i ++) printf("%lld ", rs[i]);
 63     //printf("\n");
 64     return false;
 65 }
 66 
 67 void get()
 68 {
 69     us LL x;
 70     for(R i = 0; i <= len; i ++)//枚举对哪一位进行操作,
 71     {//如果是插入的话就是在这个位置的后面插入
 72         if(i)//只有i > 0才可以删除和修改
 73         {
 74             for(R j = 0; j < 26; j ++)//枚举修改成哪个
 75             {
 76                 x = ls[i - 1] * qw[len - i + 1] + 1LL * (j + 'a') * qw[len - i] + rs[i + 1];
 77                 if(half(x)) ans ++;                
 78             }
 79             x = ls[i - 1] * qw[len - i] + rs[i + 1];
 80             if(half(x)) ans ++;
 81         }
 82         for(R j = 0; j < 26; j ++)//枚举在后面插入哪个
 83         {
 84             x = ls[i] * qw[len - i + 1] + 1LL * (j + 'a') * qw[len - i] + rs[i + 1];
 85             if(half(x)) ans ++;
 86         }
 87     }
 88     printf("%d\n", ans);
 89 }
 90 
 91 void work()
 92 {
 93     for(R i = 1; i <= m; i ++) 
 94     {
 95         if(check()) continue;
 96         get();
 97     }
 98 }
 99 
100 int main()
101 {
102 //    freopen("in.in", "r", stdin);
103     pre();
104     work();
105 //    fclose(stdin);
106     return 0;
107 }
View Code

 

posted @ 2018-12-04 22:18  ww3113306  阅读(225)  评论(0编辑  收藏  举报
知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 未本地化版本许可协议进行许可。