• 【BZOJ4259】 残缺的字符串


    Description

    很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。
    你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?

    Input

    第一行包含两个正整数m,n(1<=m<=n<=300000),分别表示A串和B串的长度。
    第二行为一个长度为m的字符串A。
    第三行为一个长度为n的字符串B。
    两个串均仅由小写字母和*号组成,其中*号表示相应位置已经残缺。

    Output

    第一行包含一个整数k,表示B串中可以完全匹配A串的位置个数。
    若k>0,则第二行输出k个正整数,从小到大依次输出每个可以匹配的开头位置(下标从1开始)。

    Sample Input

    3 7
    a*b
    aebr*ob

    Sample Output

    2
    1 5

    HINT

     

    Source

    By Claris

    Solution

    对于每个字母的权值就设为1~26。*的权值设为0。两个字符可以匹配当且仅当A_i∗B_j∗(A_i−B_j )^2等于0。那么我们将这个式子展开,展开以后的每一项分别用FFT计算即可。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cmath>
     4 #include <cstring>
     5 
     6 #define R register
     7 #define maxn 1048576
     8 typedef long double db;
     9 const db pi = acosl(-1);
    10 char A[maxn], B[maxn];
    11 struct Complex {
    12     db x, y;
    13     inline Complex operator - (const Complex &that) const {return (Complex) {x - that.x, y - that.y};}
    14     inline Complex operator * (const Complex &that) const {return (Complex) {x * that.x - y * that.y, x * that.y + y * that.x};}
    15     inline void operator += (const Complex &that) {x += that.x; y += that.y;}
    16 } w[maxn];
    17 int N;
    18 void init()
    19 {
    20     R int h = N >> 1;
    21     for (R int i = 0; i < h; ++i) w[i + h] = (Complex) {cos(2 * pi / N * i), sin(2 * pi / N * i)};
    22     for (R int i = h; i--; ) w[i] = w[i << 1];
    23 }
    24 void bit_reverse(R Complex *a, R Complex *b)
    25 {
    26     for (R int i = 0; i < N; ++i) b[i] = a[i];
    27     for (R int i = 0, j = 0; i < N; ++i)
    28     {
    29         i > j ? std::swap(b[i], b[j]), 1 : 0;
    30         for (R int l = N >> 1; (j ^= l) < l; l >>= 1);
    31     }
    32 }
    33 void dft(R Complex *a)
    34 {
    35     for (R int l = 2, m = 1; m != N; l <<= 1, m <<= 1)
    36         for (R int i = 0; i < N; i += l)
    37             for (R int j = 0; j < m; ++j)
    38             {
    39                 R Complex tmp = a[i + j + m] * w[j + m];
    40                 a[i + j + m] = a[i + j] - tmp;
    41                 a[i + j] += tmp;
    42             }
    43 }
    44 Complex a[maxn], b[maxn], ta[maxn], tb[maxn], tc[maxn], ans[maxn];
    45 int aa[maxn], bb[maxn];
    46 int main()
    47 {
    48     R int la, lb;
    49     scanf("%s%s", A, B);
    50     la = strlen(A); lb = strlen(B);
    51     for (N = 1; N < (la + lb); N <<= 1);
    52     init();
    53     std::reverse(A, A + la);
    54     for (R int i = 0; i < la; ++i) A[i] == '*' ? 0 : aa[i] = A[i] - 'a' + 1;
    55     for (R int i = 0; i < lb; ++i) B[i] == '*' ? 0 : bb[i] = B[i] - 'a' + 1;
    56 
    57     for (R int i = 0; i < la; ++i) a[i].x = aa[i] * aa[i] * aa[i], a[i].y = 0;
    58     for (R int i = 0; i < lb; ++i) b[i].x = bb[i], b[i].y = 0;
    59     bit_reverse(a, ta); bit_reverse(b, tb);
    60     dft(ta); dft(tb);
    61     for (R int i = 0; i < N; ++i) ans[i] += (ta[i] * tb[i]);
    62     
    63     for (R int i = 0; i < la; ++i) a[i].x = -2 * aa[i] * aa[i], a[i].y = 0;
    64     for (R int i = 0; i < lb; ++i) b[i].x = bb[i] * bb[i], b[i].y = 0;
    65     bit_reverse(a, ta); bit_reverse(b, tb);
    66     dft(ta); dft(tb);
    67     for (R int i = 0; i < N; ++i) ans[i] += (ta[i] * tb[i]);
    68     
    69     for (R int i = 0; i < la; ++i) a[i].x = aa[i], a[i].y = 0;
    70     for (R int i = 0; i < lb; ++i) b[i].x = bb[i] * bb[i] * bb[i], b[i].y = 0;
    71     bit_reverse(a, ta); bit_reverse(b, tb);
    72     dft(ta); dft(tb);
    73     for (R int i = 0; i < N; ++i) ans[i] += (ta[i] * tb[i]);
    74     
    75     std::reverse(ans + 1, ans + N);
    76     bit_reverse(ans, tc);
    77     dft(tc);
    78 //    for (R int i = 0; i < N; ++i) printf("%lf %lf
    ", tc[i].x, tc[i].y);
    79     for (R int i = la - 1; i < lb; ++i) if (fabs(tc[i].x / N) < 0.5) printf("%d ", i - la + 2);
    80     return 0;
    81 }
    82 /*
    83 399906 399924 399942 399960 399978 399996
    84 */
    FFT

    其实这题的数据用bitset是可以水过的。不过可以卡。然后我优化了一发常数就只是最慢的数据本机3s以内了。我把代码放在这里欢迎大家来hack!  O(∩_∩)O~~

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <bitset>
      4 #include <algorithm>
      5 
      6 #define R register
      7 #define maxn 500010
      8 #define maxs 15635
      9 //#define inline 
     10 char A[maxn], B[maxn];
     11 /*inline bool eq(R char a, R char b)
     12 {
     13     return a == b || a == '*' || b == '*';
     14 }*/
     15 typedef unsigned uint;
     16 int len;
     17 
     18 #define set(v, x) (v[x >> 5] |= 1u << (x & 31))
     19 #define query(v, x) ((1u << (x & 31)) & v[x >> 5])
     20 uint p[26][32][maxs];
     21 uint aph[26][maxs], ans[maxs];
     22 inline void init(R int c)
     23 {
     24     R uint *t = p[c][0], *tt;
     25     for (R int i = 0; i <= len; ++i) t[i] = aph[c][i];
     26     for (R int i = 1; i < 32; ++i)
     27     {
     28         t = p[c][i]; tt = p[c][i - 1];
     29         for (R int j = 0; j <= len; ++j)
     30             t[j] = ((tt[j] >> 1) | ((tt[j + 1] & 1u) << 31));
     31     }
     32 }
     33 int cnt;
     34 inline void bit_and(R int c, R int l)
     35 {
     36     R int fir = l >> 5; R uint *t = p[c][l & 31];
     37     R int i = fir, j = 0;
     38     for (; i + 36 < len; i += 36, j += 36)
     39     {
     40         ans[j] &= t[i];
     41         ans[j + 1] &= t[i + 1];
     42         ans[j + 2] &= t[i + 2];
     43         ans[j + 3] &= t[i + 3];
     44         ans[j + 4] &= t[i + 4];
     45         ans[j + 5] &= t[i + 5];
     46         ans[j + 6] &= t[i + 6];
     47         ans[j + 7] &= t[i + 7];
     48         ans[j + 8] &= t[i + 8];
     49         ans[j + 9] &= t[i + 9];
     50         ans[j + 10] &= t[i + 10];
     51         ans[j + 11] &= t[i + 11];
     52         ans[j + 12] &= t[i + 12];
     53         ans[j + 13] &= t[i + 13];
     54         ans[j + 14] &= t[i + 14];
     55         ans[j + 15] &= t[i + 15];
     56         ans[j + 16] &= t[i + 16];
     57         ans[j + 17] &= t[i + 17];
     58         ans[j + 18] &= t[i + 18];
     59         ans[j + 19] &= t[i + 19];
     60         ans[j + 20] &= t[i + 20];
     61         ans[j + 21] &= t[i + 21];
     62         ans[j + 22] &= t[i + 22];
     63         ans[j + 23] &= t[i + 23];
     64         ans[j + 24] &= t[i + 24];
     65         ans[j + 25] &= t[i + 25];
     66         ans[j + 26] &= t[i + 26];
     67         ans[j + 27] &= t[i + 27];
     68         ans[j + 28] &= t[i + 28];
     69         ans[j + 29] &= t[i + 29];
     70         ans[j + 30] &= t[i + 30];
     71         ans[j + 31] &= t[i + 31];
     72         ans[j + 32] &= t[i + 32];
     73         ans[j + 33] &= t[i + 33];
     74         ans[j + 34] &= t[i + 34];
     75         ans[j + 35] &= t[i + 35];
     76     }
     77     for (; i <= len; ++i, ++j) ans[j] &= t[i];
     78 }
     79 
     80 //std::bitset<maxn> aph[26], ans;
     81 int fail[maxn];
     82 int r[maxn];
     83 inline bool cmp(R int a, R int b) {return A[a] < A[b] || (A[a] == A[b] && (a & 31) < (b & 31));}
     84 int main()
     85 {
     86 //    freopen("str.in", "r", stdin);
     87 //    freopen("str.out", "w", stdout);
     88     scanf("%s%s", A, B);
     89     R int la = strlen(A), lb = strlen(B);
     90     len = lb >> 5;
     91     R int xcnt = 0;
     92     for (R int i = 0; i < la; ++i) xcnt += A[i] == '*';
     93     for (R int i = 0; i < lb; ++i) xcnt += B[i] == '*';
     94     /*if (!xcnt)
     95     {
     96         fail[1] = 0;
     97         for (R int i = la; i; --i) A[i] = A[i - 1];
     98         for (R int i = lb; i; --i) B[i] = B[i - 1];
     99         for (R int i = 2, p = 0; i <= la; ++i)
    100         {
    101             while (p && A[p + 1] != A[i]) p = fail[p];
    102             A[p + 1] == A[i] ? ++p : 0;
    103             fail[i] = p;
    104         }
    105         for (R int i = 1, p = 0; i <= lb; ++i)
    106         {
    107             while (p && A[p + 1] != B[i]) p = fail[p];
    108             A[p + 1] == B[i] ? ++p : 0;
    109             if (p == la)
    110             {
    111                 printf("%d ", i - la + 1);
    112                 p = fail[p];
    113             }
    114         }
    115         puts("");
    116         return 0;
    117     }*/
    118     for (R int i = 0; i < lb; ++i)
    119     {
    120         if (B[i] != '*') set(aph[B[i] - 'a'], i);
    121         else for (R int j = 0; j < 26; ++j) set(aph[j], i);
    122         set(ans, i);
    123     }
    124     for (R int i = 0; i < 26; ++i) init(i);
    125 //    fprintf(stderr, "%d %d
    ", '*', 'a');
    126     for (R int i = 0; i < la; ++i) r[i] = i;
    127     std::sort(r, r + la, cmp);
    128     for (R int i = 0; i < la; ++i)
    129         if (A[r[i]] != '*')
    130             bit_and(A[r[i]] - 'a', r[i]);
    131 //            ans &= (aph[A[i] - 'a'] >> i);
    132     for (R int i = 0; i + la - 1 < lb; ++i) if (query(ans, i)) printf("%d ", i + 1); puts("");
    133     return 0;
    134 }
    bitset
  • 相关阅读:
    JNDI使用小记
    Python基础之字符串
    openstack装B之路http协议
    openstack装B之路keystone
    Python基础之列表
    openstack装B之路Keystone部署以及操作
    openstack装B之路网关协议
    纵表与横表互转的SQL
    Asp.Net请求管道中的19个事件
    jquery ajax post get
  • 原文地址:https://www.cnblogs.com/cocottt/p/7044664.html
Copyright © 2020-2023  润新知