博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
4503: 两个串
阅读量:4992 次
发布时间:2019-06-12

本文共 3281 字,大约阅读时间需要 10 分钟。

 

4503: 两个串

题意:

  求第二个串在第一个中出现了几次,用通配符。求出每个串的起始位置。

分析:

  bitset。

  一共有26个字母,求出每个字母在第一个串中出现的位置。扫一遍第二个串,ans = p[[1]] & (p[T[2]]>>1) & (p[T[3]>>3]) & ... & p[T[n]>>n]。很好理解,就是每个字符所有出现的位置往右移,如果匹配,那么这一位and后,为1。

代码:

#include
#include
#include
#include
#include
using namespace std;const int N = 200001;bitset
p[26], ans;char s[N], t[N];int main() { scanf("%s", s); int l1 = strlen(s); scanf("%s", t); int l2 = strlen(t); for (int j=0; j<26; ++j) for (int i=0; i
> i); } cout << ans.count() << "\n"; for (int i=0; i
View Code 

 

FFT的做法:

如果T出现在S中,那么有$\sum\limits_{i=0}^{m-1} (S_i-T_i)^2=0$

如果出现通配符,如果T出现在S中,那么设T[i]=0,那么有$\sum\limits_{i=0}^{m-1} (S_i-T_i)^2 \times T[i]=0$

然后将式子拆开$\sum\limits_{i=0}^{m-1} S_i^2T_i-2S_iT_i^2+T_i^3=0$

把T翻转,然后FFT即可。

当然,这只是对应到第一个位置的情况,其他的情况类似只需要将卷积后的指数改一下即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long LL;inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;}const int N = 270005;const double Pi = acos(-1.0), eps = 1e-10;struct Com{ double x, y; Com(double _x = 0, double _y = 0) { x = _x, y = _y; }}a[N], b[N], a2[N], b2[N], C[N]; double b3;Com operator + (const Com &A,const Com &B) { return Com(A.x + B.x, A.y + B.y); }Com operator - (const Com &A,const Com &B) { return Com(A.x - B.x, A.y - B.y); }Com operator * (const Com &A,const Com &B) { return Com(A.x * B.x - A.y * B.y, A.x * B.y + A.y * B.x); }char s[N], t[N];int rev[N], S[N], T[N], c[N];vector
ans;void FFT(Com *a,int len,int ty) { for (int i = 0; i < len; ++i) if (i < rev[i]) swap(a[i], a[rev[i]]); Com w1, w, u, t; for (int m = 2; m <= len; m <<= 1) { w1 = Com(cos(2 * Pi / m), ty * sin(2 * Pi / m)); for (int i = 0; i < len; i += m) { w = Com(1, 0); for (int k = 0; k < (m >> 1); ++k) { u = a[i + k], t = w * a[i + k + (m >> 1)]; a[i + k] = u + t; a[i + k + (m >> 1)] = u - t; w = w * w1; } } }}int main() { scanf("%s%s", s, t); int n = strlen(s), m = strlen(t), len = 1, lg = 0; while (len < n + m) len <<= 1, lg ++; for (int i = 0; i < len; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1)); for (int i = 0; i < n; ++i) S[i] = s[i] - 'a' + 1; for (int i = 0; i < m; ++i) T[i] = t[i] == '?' ? 0 : t[i] - 'a' + 1; for (int i = 0; i < n; ++i) a[i] = Com(2 * S[i], 0), a2[i] = Com(S[i] * S[i], 0); reverse(T, T + m); for (int i = 0; i < m; ++i) b[i] = Com(T[i], 0), b2[i] = Com(T[i] * T[i], 0), b3 += T[i] * T[i] * T[i]; FFT(a2, len, 1); FFT(b, len, 1); FFT(a, len, 1); FFT(b2, len, 1); for (int i = 0; i < len; ++i) C[i] = a2[i] * b[i] - a[i] * b2[i]; FFT(C, len, -1); for (int i = 0; i < len; ++i) C[i].x = C[i].x / (double)len; for (int i = 0; i < len; ++i) c[i] = floor(C[i].x + b3 + 0.5); for (int i = m - 1; i < n; ++i) if (c[i] == 0) ans.push_back(i - m + 1); printf("%d\n", (int)ans.size()); for (int i = 0; i < (int)ans.size(); ++i) printf("%d\n", ans[i]); return 0;}
View Code

 

转载于:https://www.cnblogs.com/mjtcn/p/9762346.html

你可能感兴趣的文章
启动eclipse出现错误Java was started but returned exit =一个数字
查看>>
myBatis模糊查找
查看>>
数据结构与算法之五 链接列表
查看>>
java 对象数组
查看>>
设计模式读书笔记-单件模式(创建型模式)
查看>>
Oracle——热备份
查看>>
Vue路由history模式踩坑记录:nginx配置解决404问题
查看>>
c# 多张图片合成一张图片
查看>>
使用SQL Server 2008的事务日志传送功能备份数据库(logshiping)
查看>>
AngularJS多个ng-app只解析第一个的问题
查看>>
强制修改常量的值
查看>>
Grunt 初体验
查看>>
hive跑mapreduce报java.lang.RuntimeException: Error in configuring object
查看>>
ArcGIS中的坐标系统定义与投影转换方法
查看>>
机械臂的碰撞检测资料
查看>>
[UnityShader基础]01.渲染队列
查看>>
字符串转整型C++
查看>>
随机生成红包算法
查看>>
Datatable get请求传参应用
查看>>
杭电1170
查看>>