bzoj4503 两个串

题意:给定两个串s,t。其中t可能含有?,可以代表任一字符。

求t在s中一共出现了多少次。

解:

我有个想法是在后缀自动机上DFS,然后发现不记忆化会超时,记忆化又不对。

正解是FFT。我们发现如果把问号看做0,那么两个字符匹配就是(a - b)b = 0

然后整串匹配就是∑(a - b)²b = 0

我们发现这个是顺着来的,不好搞,那么把第二个串reverse,就变成卷积了。

∑a²b - 2ab² + b3 = 0,前两项可以看做是两个卷积,直接卷起来。这时卷积多项式的系数就是串t在s中的某个位置进行匹配的结果。

第三项对于t在s中的任一位置来说都是相同的,直接加。

然后把答案 + 0.5转int就行了,某个位置为0就是答案。

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <cmath>
  5 
  6 typedef long long LL;
  7 const int N = 100010;
  8 const double pi = 3.1415926535897932384626, eps = 1e-9;
  9 
 10 struct cp {
 11     double x, y;
 12     cp(double X = 0.0, double Y = 0.0) {
 13         x = X;
 14         y = Y;
 15     }
 16     inline cp operator +(const cp &w) const {
 17         return cp(x + w.x, y + w.y);
 18     }
 19     inline cp operator -(const cp &w) const {
 20         return cp(x - w.x, y - w.y);
 21     }
 22     inline cp operator *(const cp &w) const {
 23         return cp(x * w.x - y * w.y, x * w.y + y * w.x);
 24     }
 25 }a[N << 2], b[N << 2];
 26 
 27 int r[N << 2];
 28 char s[N], str[N];
 29 double ans[N << 2];
 30 
 31 inline void FFT(int n, cp *a, int f) {
 32     for(int i = 0; i < n; i++) {
 33         if(i < r[i]) {
 34             std::swap(a[i], a[r[i]]);
 35         }
 36     }
 37 
 38     for(int len = 1; len < n; len <<= 1) {
 39         cp Wn(cos(pi / len), f * sin(pi / len));
 40         for(int i = 0; i < n; i += (len << 1)) {
 41             cp w(1, 0);
 42             for(int j = 0; j < len; j++) {
 43                 cp t = a[i + len + j] * w;
 44                 a[i + len + j] = a[i + j] - t;
 45                 a[i + j] = a[i + j] + t;
 46                 w = w * Wn;
 47             }
 48         }
 49     }
 50 
 51     if(f == -1) {
 52         for(int i = 0; i <= n; i++) {
 53             a[i].x /= n;
 54         }
 55     }
 56     return;
 57 }
 58 
 59 int main() {
 60 
 61     scanf("%s%s", s, str);
 62     int n = strlen(s) - 1, m = strlen(str) - 1;
 63     LL b3 = 0;
 64     for(int i = 0; i <= n; i++) {
 65         a[i].x = (s[i] - 'a' + 1) * (s[i] - 'a' + 1);
 66     }
 67     for(int i = 0; i <= m; i++) {
 68         if(str[i] == '?') {
 69             b[m - i].x = 0;
 70         }
 71         else {
 72             b[m - i].x = (str[i] - 'a' + 1);
 73             b3 += (str[i] - 'a' + 1) * (str[i] - 'a' + 1) * (str[i] - 'a' + 1);
 74         }
 75     }
 76 
 77     int len = 2, lm = 1;
 78     while(len <= n + m) {
 79         len <<= 1;
 80         lm++;
 81     }
 82     for(int i = 1; i <= len; i++) {
 83         r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1));
 84     }
 85 
 86     FFT(len, a, 1);
 87     FFT(len, b, 1);
 88     for(int i = 0; i <= len; i++) {
 89         a[i] = a[i] * b[i];
 90     }
 91     FFT(len, a, -1);
 92     for(int i = 0; i <= len; i++) {
 93         ans[i] = a[i].x;
 94     }
 95 
 96     for(int i = 0; i <= n; i++) {
 97         a[i].x = 2 * (s[i] - 'a' + 1);
 98         a[i].y = 0;
 99     }
100     for(int i = n + 1; i <= len; i++) {
101         a[i].x = a[i].y = 0;
102     }
103     for(int i = 0; i <= m; i++) {
104         if(str[i] == '?') {
105             b[m - i].x = 0;
106         }
107         else {
108             b[m - i].x = (str[i] -'a' + 1) * (str[i] - 'a' + 1);
109         }
110         b[m - i].y = 0;
111     }
112     for(int i = m + 1; i <= len; i++) {
113         b[i].x = b[i].y = 0;
114     }
115     FFT(len, a, 1);
116     FFT(len, b, 1);
117     for(int i = 0; i <= len; i++) {
118         a[i] = a[i] * b[i];
119     }
120     FFT(len, a, -1);
121     for(int i = 0; i <= len; i++) {
122         ans[i] -= a[i].x;
123     }
124 
125     for(int i = 0; i <= len; i++) {
126         ans[i] += b3;
127     }
128 
129     int temp = 0;
130     for(int i = m; i <= n; i++) {
131         temp += int(ans[i] + 0.5) == 0;
132     }
133     printf("%d\n", temp);
134     for(int i = m; i <= n; i++) {
135         if(int(ans[i] + 0.5) == 0) {
136             printf("%d\n", i - m);
137         }
138     }
139     return 0;
140 }
AC代码

双倍经验:BZOJ4259

  1 #include  <cstdio>
  2 #include <cmath>
  3 #include <algorithm>
  4 #include <cstring>
  5 
  6 const int N = 300010;
  7 const double pi = 3.1415926535897932384626;
  8 
  9 struct cp {
 10     double x, y;
 11     cp(double X = 0, double Y = 0) {
 12         x = X;
 13         y = Y;
 14     }
 15     inline cp operator +(const cp &w) const {
 16         return cp(x + w.x, y + w.y);
 17     }
 18     inline cp operator -(const cp &w) const {
 19         return cp(x - w.x, y - w.y);
 20     }
 21     inline cp operator *(const cp &w) const {
 22         return cp(x * w.x - y * w.y, x * w.y + y * w.x);
 23     }
 24 }a[N << 2], b[N << 2];
 25 
 26 int r[N << 2];
 27 char s[N], str[N];
 28 double ans[N << 2];
 29 
 30 inline void FFT(int n, cp *a, int f) {
 31     for(int i = 0; i < n; i++) {
 32         if(i < r[i]) {
 33             std::swap(a[i], a[r[i]]);
 34         }
 35     }
 36 
 37     for(int len = 1; len < n; len <<= 1) {
 38         cp Wn(cos(pi / len), f * sin(pi / len));
 39         for(int i = 0; i < n; i += (len << 1)) {
 40             cp w(1, 0);
 41             for(int j = 0; j < len; j++) {
 42                 cp t = a[i + len + j] * w;
 43                 a[i + len + j] = a[i + j] - t;
 44                 a[i + j] = a[i + j] + t;
 45                 w = w * Wn;
 46             }
 47         }
 48     }
 49 
 50     if(f == -1) {
 51         for(int i = 0; i <= n; i++) {
 52             a[i].x /= n;
 53         }
 54     }
 55     return;
 56 }
 57 
 58 int main() {
 59     int m, n;
 60     scanf("%d%d", &m, &n);
 61     m--;
 62     n--;
 63     scanf("%s%s", str, s);
 64     for(int i = 0; i <= n; i++) {
 65         s[i] = (s[i] == '*' ? 0 : s[i] - 'a' + 1);
 66     }
 67     for(int i = 0; i <= m; i++) {
 68         str[i] = (str[i] == '*' ? 0 : str[i] - 'a' + 1);
 69     }
 70     int len = 2, lm = 1;
 71     while(len <= n + m) {
 72         len <<= 1;
 73         lm++;
 74     }
 75     for(int i = 1; i <= len; i++) {
 76         r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lm - 1));
 77     }
 78 
 79     for(int i = 0; i <= n; i++) {
 80         a[i] = cp(1ll * s[i] * s[i] * s[i], 0);
 81     }
 82     for(int i = 0; i <= m; i++) {
 83         b[i] = cp(str[m - i], 0);
 84     }
 85     FFT(len, a, 1);
 86     FFT(len, b, 1);
 87     for(int i = 0; i <= len; i++) {
 88         a[i] = a[i] * b[i];
 89     }
 90     FFT(len, a, -1);
 91     for(int i = 0; i <= len; i++) {
 92         ans[i] = a[i].x;
 93     }
 94 
 95     for(int i = 0; i <= n; i++) {
 96         a[i] = cp(1ll * s[i] * s[i], 0);
 97     }
 98     for(int i = 0; i <= m; i++) {
 99         b[i] = cp(1ll * str[m - i] * str[m - i], 0);
100     }
101     for(int i = n + 1; i <= len; i++) {
102         a[i] = cp(0, 0);
103     }
104     for(int i = m + 1; i <= len; i++) {
105         b[i] = cp(0, 0);
106     }
107     FFT(len, a, 1);
108     FFT(len, b, 1);
109     for(int i = 0; i <= len; i++) {
110         a[i] = a[i] * b[i];
111     }
112     FFT(len, a, -1);
113     for(int i = 0; i <= len; i++) {
114         ans[i] -= 2 * a[i].x;
115     }
116 
117     for(int i = 0; i <= n; i++) {
118         a[i] = cp(s[i], 0);
119     }
120     for(int i = 0; i <= m; i++) {
121         b[i] = cp(1ll * str[m - i] * str[m - i] * str[m - i], 0);
122     }
123     for(int i = n + 1; i <= len; i++) {
124         a[i] = cp(0, 0);
125     }
126     for(int i = m + 1; i <= len; i++) {
127         b[i] = cp(0, 0);
128     }
129     FFT(len, a, 1);
130     FFT(len, b, 1);
131     for(int i = 0; i <= len; i++) {
132         a[i] = a[i] * b[i];
133     }
134     FFT(len, a, -1);
135     for(int i = 0; i <= len; i++) {
136         ans[i] += a[i].x;
137     }
138 
139     int temp = 0;
140     for(int i = m; i <= n; i++) {
141         temp += (int)(ans[i] + 0.5) == 0;
142     }
143     printf("%d\n", temp);
144     for(int i = m; i <= n; i++) {
145         if((int)(ans[i] + 0.5) == 0) {
146             printf("%d ", i - m + 1);
147         }
148     }
149     return 0;
150 }
AC代码

 

posted @ 2019-01-09 14:40  huyufeifei  阅读(165)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜