bupt summer training for 16 #8 ——字符串处理
https://vjudge.net/contest/175596#overview
A.设第i次出现的位置左右端点分别为Li,Ri
初始化L0 = 0,则有ans = sum{ (L[i] - L[i-1]) * (n + 1 - Ri) }
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; int last = ; char s[]; long long ans; int main() {
scanf("%s", s + );
int n = strlen(s + );
for(int i = ;i <= n;i ++) {
if(i + <= n && s[i] == 'b' && s[i + ] == 'e' && s[i + ] == 'a' && s[i + ] == 'r') {
ans += 1ll * (i - last) * (n + - i - );
last = i;
i += ;
}
}
cout << ans;
return ;
}
B.AC自动机板子题,我的板子常数很大
#include <queue>
#include <cstdio>
#include <cstring> using namespace std; const int maxn = ; struct trie {
int next[maxn][], fail[maxn], end[maxn];
int L, root;
queue <int> q; int newnode() {
for(int i = ;i < ;i ++)
next[L][i] = -;
end[L] = ;
return L ++;
} void clear() {
L = ;
root = newnode();
} int idx(char c) {
return c - 'a';
} void insert(char *buf) {
int len = strlen(buf), now = root, c;
for(int i = ;i < len;i ++) {
c = idx(buf[i]);
if(next[now][c] == -)
next[now][c] = newnode();
now = next[now][c];
}
end[now] ++;
} void build() {
for(int i = ;i < ;i ++) {
if(next[root][i] == -)
next[root][i] = root;
else {
fail[next[root][i]] = root;
q.push(next[root][i]);
}
}
while(!q.empty()) {
int now = q.front();
q.pop();
for(int i = ;i < ;i ++) {
if(next[now][i] == -)
next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
q.push(next[now][i]);
}
}
}
} int query(char *buf) {
int len = strlen(buf), now = root, res = , tmp;
for(int i = ;i < len;i ++) {
tmp = now = next[now][idx(buf[i])];
while(tmp != root) {
res += end[tmp];
end[tmp] = ;
tmp = fail[tmp];
}
}
return res;
}
}; trie ac; int Case, n; char buf[]; int main() {
scanf("%d", &Case);
while(Case --) {
scanf("%d", &n), ac.clear();
while(n --) scanf("%s", buf), ac.insert(buf);
scanf("%s", buf), ac.build();
printf("%d\n", ac.query(buf));
}
return ;
}
C.考察对KMP中next数组的理解,由一个串重复而来
所以就是max(i - next[i])
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; char s[]; int nex[]; int main() {
int i, j, ans, len;
while(~scanf("%s", s)) {
len = strlen(s);
nex[] = -;
ans = ;
for(i = ;i < len;i ++) {
j = nex[i - ];
while(j >= && s[j + ] != s[i]) j = nex[j];
if(s[j + ] == s[i]) {
nex[i] = j + ;
ans = max(ans, i - nex[i]);
}
else nex[i] = -, ans = max(ans, i + );
}
printf("%d\n", ans);
}
return ;
}
D.令a[i] -= a[i + 1],题目就变成了
求数列中出现次数不小于2次的最长重复子串
后缀数组一个典型问题,二分子串长度即可
(考场上观察了半天手里板子的接口...然后放弃了)
E.先假设要由空串刷成串2,区间DP即可
dp[i][j]代表把 i-j 这段刷成串2需要的最少次数
可能分成几段分开去刷,所以不能直接ans = dp[L][R] (s1[L] != s2[L],s1[R] != s2[R])
利用f[i]代表 1-i 这段由串1刷成串2的最少次数
ans = f[n]
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; int n, dp[][], f[]; char s1[], s2[]; int main() {
while(~scanf("%s %s", s1 + , s2 + )) {
n = strlen(s1 + );
memset(dp, 0x3f, sizeof dp);
for(int d = ;d <= n;d ++)
for(int i = ;i + d - <= n;i ++) {
int j = i + d - ;
if(i == j) dp[i][i] = ;
else if(j == i + ) dp[i][j] = - (s2[i] == s2[j]);
else {
for(int k = i;k < j;k ++)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + ][j] - (s2[i] == s2[k + ]));
}
}
for(int i = ;i <= n;i ++) {
f[i] = dp[][i];
if(s1[i] == s2[i]) f[i] = min(f[i - ], f[i]);
else
for(int j = ;j < i;j ++)
f[i] = min(f[i], f[j] + dp[j + ][i]);
}
printf("%d\n", f[n]);
}
return ;
}
F.简单的字典树
#include <cstdio>
#include <cstring> const int maxn = ; struct trie {
int ch[maxn][];
int val[maxn];
int siz; void init() {
siz = ;
memset(ch, , sizeof ch);
memset(val, , sizeof val);
} void insert(int x) {
int i, u, c;
int num[] = {};
for(i = ;i < ;i ++)
num[i] = x & ( << i);
for(i = u = ;i < ;i ++) {
c = (num[ - i] != );
if(!ch[u][c]) ch[u][c] = siz ++;
u = ch[u][c], val[u] ++;
}
val[] ++;
} void de1ete(int x) {
int i, u, c;
int num[] = {};
for(i = ;i < ;i ++)
num[i] = x & ( << i);
for(i = u = ;i < ;i ++) {
u = ch[u][(num[ - i] != )];
val[u] --;
}
val[] --;
} void query(int x) {
int i, u, c, ans = ;
int num[] = {};
for(i = ;i < ;i ++)
num[i] = x & ( << i);
for(i = u = ;i < ;i ++) {
c = !(num[ - i] != );
if(ch[u][c] && val[ch[u][c]]) ans |= ( << ( - i)), u = ch[u][c];
else u = ch[u][!c];
}
printf("%d\n", ans);
}
}; trie now; int n, x; char str[]; int main() {
now.init();
now.insert();
scanf("%d", &n);
while(n --) {
scanf("%s %d", str, &x);
switch(str[]) {
case '+':now.insert(x);break;
case '-':now.de1ete(x);break;
case '?':now.query(x);break;
}
}
return ;
}
G.
H.
I.
J.
K.最长回文子串,直接上马拉车
板子不长,mp[i] - 1 表示以 i 为中心的最长回文串长度
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = ; char str[], s[maxn], ma[maxn], ans[maxn]; int mp[maxn], l, len; map <char, char> p; void manacher() {
l = ;
ma[l ++] = '$';
ma[l ++] = '#';
for(int i = ;i < len;i ++)
ma[l ++] = s[i], ma[l ++] = '#';
ma[l] = ;
int mx = , id = ;
for(int i = ;i < l;i ++) {
mp[i] = mx > i ? min(mp[ * id - i], mx - i) : ;
while(ma[i + mp[i]] == ma[i - mp[i]]) mp[i] ++;
if(i + mp[i] > mx) mx = i + mp[i], id = i;
}
} int main() {
while(~scanf("%s %s", str, s)) {
len = strlen(s);
manacher();
int leng = , pos = -;
for(int i = ;i < l;i ++)
if(mp[i] > leng)
leng = mp[i], pos = i;
leng --;
if(leng == ) {
puts("No solution!");
continue;
}
if(pos & ) {
printf("%d %d\n", pos / - leng / , pos / - leng / + leng - );
for(int i = pos / - leng / , j = ;j <= leng;i ++, j ++)
ans[j] = s[i];
}
else {
printf("%d %d\n", pos / - leng / - , pos / - leng / + leng - );
for(int i = pos / - leng / - , j = ;j <= leng;i ++, j ++)
ans[j] = s[i];
}
ans[leng + ] = ;
int dis = 'a' - str[];
for(int i = ;i < ;i ++)
p['a' + i] = 'a' + (i + dis + ) % ;
for(int i = ;i <= leng;i ++)
ans[i] = p[ans[i]];
puts(ans + );
}
return ;
}
L.变换同D题,然后就是裸的KMP了
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = ; char str[], s[maxn], ma[maxn], ans[maxn]; int mp[maxn], l, len; map <char, char> p; void manacher() {
l = ;
ma[l ++] = '$';
ma[l ++] = '#';
for(int i = ;i < len;i ++)
ma[l ++] = s[i], ma[l ++] = '#';
ma[l] = ;
int mx = , id = ;
for(int i = ;i < l;i ++) {
mp[i] = mx > i ? min(mp[ * id - i], mx - i) : ;
while(ma[i + mp[i]] == ma[i - mp[i]]) mp[i] ++;
if(i + mp[i] > mx) mx = i + mp[i], id = i;
}
} int main() {
while(~scanf("%s %s", str, s)) {
len = strlen(s);
manacher();
int leng = , pos = -;
for(int i = ;i < l;i ++)
if(mp[i] > leng)
leng = mp[i], pos = i;
leng --;
if(leng == ) {
puts("No solution!");
continue;
}
if(pos & ) {
printf("%d %d\n", pos / - leng / , pos / - leng / + leng - );
for(int i = pos / - leng / , j = ;j <= leng;i ++, j ++)
ans[j] = s[i];
}
else {
printf("%d %d\n", pos / - leng / - , pos / - leng / + leng - );
for(int i = pos / - leng / - , j = ;j <= leng;i ++, j ++)
ans[j] = s[i];
}
ans[leng + ] = ;
int dis = 'a' - str[];
for(int i = ;i < ;i ++)
p['a' + i] = 'a' + (i + dis + ) % ;
for(int i = ;i <= leng;i ++)
ans[i] = p[ans[i]];
puts(ans + );
}
return ;
}
bupt summer training for 16 #8 ——字符串处理的更多相关文章
- bupt summer training for 16 #7 ——搜索与DP
https://vjudge.net/contest/174962#overview A.我们发现重点在于x,y只要累加就ok了 在每个x上只有上下两种状态,所以可以记忆化搜索 f[0/1][i]表示 ...
- bupt summer training for 16 #6 ——图论
https://vjudge.net/contest/174020 A.100条双向边,每个点最少连2个边 所以最多100个点,点的标号需要离散化 然后要求恰好经过n条路径 快速幂,乘法过程就是flo ...
- bupt summer training for 16 #5 ——数据结构
https://vjudge.net/contest/173780 A.假设 Pt = i,则由Ppi = i得 Ppt = t = Pi 所以就有 if Pt = i then Pi = t #in ...
- bupt summer training for 16 #4 ——数论
https://vjudge.net/contest/173277#overview A.平方差公式后变为 n = (x + y)(x - y) 令 t = x - y ,变成 n = (t + 2x ...
- bupt summer training for 16 #3 ——构造
https://vjudge.net/contest/172464 后来补题发现这场做的可真他妈傻逼 A.签到傻逼题,自己分情况 #include <cstdio> #include &l ...
- bupt summer training for 16 #2 ——计算几何
https://vjudge.net/contest/171368#overview A.一个签到题,用叉积来判断一个点在一条线的哪个方向 可以二分,数据范围允许暴力 #include <cst ...
- bupt summer training for 16 #1 ——简单题目
D.What a Mess 给n个数,求其中能满足 a[i] % a[j] == 0 的数对之和 n = 1W,max_ai = 100W 不是很大,所以就直接筛就可以了 计算可得最高复杂度 < ...
- leecode刷题(16)-- 字符串转换整数
leecode刷题(16)-- 字符串转换整数 字符串转换整数 描述: 请你来实现一个 atoi 函数,使其能将字符串转换成整数. 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格 ...
- GUID转换成16位字符串或19位唯一字符串
整理几个经常使用GUID转换成16位字符串或19位唯一字符串方法: /// <summary> /// 依据GUID获取16位的唯一字符串 /// Author : 付义方 /// < ...
随机推荐
- P3092 [USACO13NOV]没有找零No Change 状压dp
这个题有点意思,其实不是特别难,但是不太好想...中间用二分找最大的可买长度就行了. 题干: 题目描述 Farmer John <= K <= ), each with value .., ...
- mkisofs
createrepo -g /enp/comps.xml . yum -y --downloadonly --downloaddir=/enp/Packages upgrade mkisofs -o ...
- astgo-官方提供的使用技巧大全
Astgo服务器相关: 1.Astgo支持双IP绑定,比如联通.电信IP,Astgo 默认SIP端口 5080和5061 菜单: 选项->系统设置 可以设置以上参数 2.支持RC4加密,自动判断 ...
- poj1611 并查集 (路径压缩)
http://poj.org/problem?id=1611 题目大意: 有一个学校,有N个学生,编号为0-N-1,现在0号学生感染了非典,凡是和0在一个社团的人就会感染,并且这些人如果还参加了别的社 ...
- ural 1017. Staircases(dp)
http://acm.timus.ru/problem.aspx?space=1&num=1017 题意:有n块砖,要求按照严格递增的个数摆放成楼梯,求楼梯的摆放种类数. 思路:状态转移方程: ...
- 常见的Java Script内存泄露原因及解决方案
前言 内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了 ...
- 如何写出网页高性能的DOM来提升网页的加载速度
为什么要写高性能DOM? 一个网站,在页面上承载最多内容的就是DOM,而且无论是我们通过加载JS.加载图片,他们也是通过写HTML标签来实现的.而我们性能优化要做的无非就是几大块: 站点的网络消耗 D ...
- skiing 暴力搜索 + 动态规划
我的代码上去就是 直接纯粹的 暴力 . 居然没有超时 200ms 可能数据比较小 一会在优化 #include<stdio.h> #include<string.h ...
- Task.Run 和 Task.Factory.StartNew
在.Net 4中,Task.Factory.StartNew是启动一个新Task的首选方法.它有很多重载方法,使它在具体使用当中可以非常灵活,通过设置可选参数,可以传递任意状态,取消任务继续执行,甚至 ...
- PHP开发之旅-提取表单提交内容发送邮件
在实际项目开发中,我们经常需要得到用户的反馈信息并及时回复.普通的留言板有一定的内容限制,而邮件则能满足这个需求.今天给大家演示一下怎么利用PHP发送电子邮件. 1.创建表单 <form nam ...