https://vjudge.net/contest/175596#overview

A.设第i次出现的位置左右端点分别为Li,Ri

初始化L0 = 0,则有ans = sum{ (L[i] - L[i-1]) * (n + 1 - Ri) }

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7.  
  8. int last = ;
  9.  
  10. char s[];
  11.  
  12. long long ans;
  13.  
  14. int main() {
  15. scanf("%s", s + );
  16. int n = strlen(s + );
  17. for(int i = ;i <= n;i ++) {
  18. if(i + <= n && s[i] == 'b' && s[i + ] == 'e' && s[i + ] == 'a' && s[i + ] == 'r') {
  19. ans += 1ll * (i - last) * (n + - i - );
  20. last = i;
  21. i += ;
  22. }
  23. }
  24. cout << ans;
  25. return ;
  26. }

B.AC自动机板子题,我的板子常数很大

  1. #include <queue>
  2. #include <cstdio>
  3. #include <cstring>
  4.  
  5. using namespace std;
  6.  
  7. const int maxn = ;
  8.  
  9. struct trie {
  10. int next[maxn][], fail[maxn], end[maxn];
  11. int L, root;
  12. queue <int> q;
  13.  
  14. int newnode() {
  15. for(int i = ;i < ;i ++)
  16. next[L][i] = -;
  17. end[L] = ;
  18. return L ++;
  19. }
  20.  
  21. void clear() {
  22. L = ;
  23. root = newnode();
  24. }
  25.  
  26. int idx(char c) {
  27. return c - 'a';
  28. }
  29.  
  30. void insert(char *buf) {
  31. int len = strlen(buf), now = root, c;
  32. for(int i = ;i < len;i ++) {
  33. c = idx(buf[i]);
  34. if(next[now][c] == -)
  35. next[now][c] = newnode();
  36. now = next[now][c];
  37. }
  38. end[now] ++;
  39. }
  40.  
  41. void build() {
  42. for(int i = ;i < ;i ++) {
  43. if(next[root][i] == -)
  44. next[root][i] = root;
  45. else {
  46. fail[next[root][i]] = root;
  47. q.push(next[root][i]);
  48. }
  49. }
  50. while(!q.empty()) {
  51. int now = q.front();
  52. q.pop();
  53. for(int i = ;i < ;i ++) {
  54. if(next[now][i] == -)
  55. next[now][i] = next[fail[now]][i];
  56. else {
  57. fail[next[now][i]] = next[fail[now]][i];
  58. q.push(next[now][i]);
  59. }
  60. }
  61. }
  62. }
  63.  
  64. int query(char *buf) {
  65. int len = strlen(buf), now = root, res = , tmp;
  66. for(int i = ;i < len;i ++) {
  67. tmp = now = next[now][idx(buf[i])];
  68. while(tmp != root) {
  69. res += end[tmp];
  70. end[tmp] = ;
  71. tmp = fail[tmp];
  72. }
  73. }
  74. return res;
  75. }
  76. };
  77.  
  78. trie ac;
  79.  
  80. int Case, n;
  81.  
  82. char buf[];
  83.  
  84. int main() {
  85. scanf("%d", &Case);
  86. while(Case --) {
  87. scanf("%d", &n), ac.clear();
  88. while(n --) scanf("%s", buf), ac.insert(buf);
  89. scanf("%s", buf), ac.build();
  90. printf("%d\n", ac.query(buf));
  91. }
  92. return ;
  93. }

C.考察对KMP中next数组的理解,由一个串重复而来

所以就是max(i - next[i])

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4.  
  5. using namespace std;
  6.  
  7. char s[];
  8.  
  9. int nex[];
  10.  
  11. int main() {
  12. int i, j, ans, len;
  13. while(~scanf("%s", s)) {
  14. len = strlen(s);
  15. nex[] = -;
  16. ans = ;
  17. for(i = ;i < len;i ++) {
  18. j = nex[i - ];
  19. while(j >= && s[j + ] != s[i]) j = nex[j];
  20. if(s[j + ] == s[i]) {
  21. nex[i] = j + ;
  22. ans = max(ans, i - nex[i]);
  23. }
  24. else nex[i] = -, ans = max(ans, i + );
  25. }
  26. printf("%d\n", ans);
  27. }
  28. return ;
  29. }

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]

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4.  
  5. using namespace std;
  6.  
  7. int n, dp[][], f[];
  8.  
  9. char s1[], s2[];
  10.  
  11. int main() {
  12. while(~scanf("%s %s", s1 + , s2 + )) {
  13. n = strlen(s1 + );
  14. memset(dp, 0x3f, sizeof dp);
  15. for(int d = ;d <= n;d ++)
  16. for(int i = ;i + d - <= n;i ++) {
  17. int j = i + d - ;
  18. if(i == j) dp[i][i] = ;
  19. else if(j == i + ) dp[i][j] = - (s2[i] == s2[j]);
  20. else {
  21. for(int k = i;k < j;k ++)
  22. dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + ][j] - (s2[i] == s2[k + ]));
  23. }
  24. }
  25. for(int i = ;i <= n;i ++) {
  26. f[i] = dp[][i];
  27. if(s1[i] == s2[i]) f[i] = min(f[i - ], f[i]);
  28. else
  29. for(int j = ;j < i;j ++)
  30. f[i] = min(f[i], f[j] + dp[j + ][i]);
  31. }
  32. printf("%d\n", f[n]);
  33. }
  34. return ;
  35. }

F.简单的字典树

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. const int maxn = ;
  5.  
  6. struct trie {
  7. int ch[maxn][];
  8. int val[maxn];
  9. int siz;
  10.  
  11. void init() {
  12. siz = ;
  13. memset(ch, , sizeof ch);
  14. memset(val, , sizeof val);
  15. }
  16.  
  17. void insert(int x) {
  18. int i, u, c;
  19. int num[] = {};
  20. for(i = ;i < ;i ++)
  21. num[i] = x & ( << i);
  22. for(i = u = ;i < ;i ++) {
  23. c = (num[ - i] != );
  24. if(!ch[u][c]) ch[u][c] = siz ++;
  25. u = ch[u][c], val[u] ++;
  26. }
  27. val[] ++;
  28. }
  29.  
  30. void de1ete(int x) {
  31. int i, u, c;
  32. int num[] = {};
  33. for(i = ;i < ;i ++)
  34. num[i] = x & ( << i);
  35. for(i = u = ;i < ;i ++) {
  36. u = ch[u][(num[ - i] != )];
  37. val[u] --;
  38. }
  39. val[] --;
  40. }
  41.  
  42. void query(int x) {
  43. int i, u, c, ans = ;
  44. int num[] = {};
  45. for(i = ;i < ;i ++)
  46. num[i] = x & ( << i);
  47. for(i = u = ;i < ;i ++) {
  48. c = !(num[ - i] != );
  49. if(ch[u][c] && val[ch[u][c]]) ans |= ( << ( - i)), u = ch[u][c];
  50. else u = ch[u][!c];
  51. }
  52. printf("%d\n", ans);
  53. }
  54. };
  55.  
  56. trie now;
  57.  
  58. int n, x;
  59.  
  60. char str[];
  61.  
  62. int main() {
  63. now.init();
  64. now.insert();
  65. scanf("%d", &n);
  66. while(n --) {
  67. scanf("%s %d", str, &x);
  68. switch(str[]) {
  69. case '+':now.insert(x);break;
  70. case '-':now.de1ete(x);break;
  71. case '?':now.query(x);break;
  72. }
  73. }
  74. return ;
  75. }

G.

H.

I.

J.

K.最长回文子串,直接上马拉车

板子不长,mp[i] - 1 表示以 i 为中心的最长回文串长度

  1. #include <map>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7.  
  8. const int maxn = ;
  9.  
  10. char str[], s[maxn], ma[maxn], ans[maxn];
  11.  
  12. int mp[maxn], l, len;
  13.  
  14. map <char, char> p;
  15.  
  16. void manacher() {
  17. l = ;
  18. ma[l ++] = '$';
  19. ma[l ++] = '#';
  20. for(int i = ;i < len;i ++)
  21. ma[l ++] = s[i], ma[l ++] = '#';
  22. ma[l] = ;
  23. int mx = , id = ;
  24. for(int i = ;i < l;i ++) {
  25. mp[i] = mx > i ? min(mp[ * id - i], mx - i) : ;
  26. while(ma[i + mp[i]] == ma[i - mp[i]]) mp[i] ++;
  27. if(i + mp[i] > mx) mx = i + mp[i], id = i;
  28. }
  29. }
  30.  
  31. int main() {
  32. while(~scanf("%s %s", str, s)) {
  33. len = strlen(s);
  34. manacher();
  35. int leng = , pos = -;
  36. for(int i = ;i < l;i ++)
  37. if(mp[i] > leng)
  38. leng = mp[i], pos = i;
  39. leng --;
  40. if(leng == ) {
  41. puts("No solution!");
  42. continue;
  43. }
  44. if(pos & ) {
  45. printf("%d %d\n", pos / - leng / , pos / - leng / + leng - );
  46. for(int i = pos / - leng / , j = ;j <= leng;i ++, j ++)
  47. ans[j] = s[i];
  48. }
  49. else {
  50. printf("%d %d\n", pos / - leng / - , pos / - leng / + leng - );
  51. for(int i = pos / - leng / - , j = ;j <= leng;i ++, j ++)
  52. ans[j] = s[i];
  53. }
  54. ans[leng + ] = ;
  55. int dis = 'a' - str[];
  56. for(int i = ;i < ;i ++)
  57. p['a' + i] = 'a' + (i + dis + ) % ;
  58. for(int i = ;i <= leng;i ++)
  59. ans[i] = p[ans[i]];
  60. puts(ans + );
  61. }
  62. return ;
  63. }

L.变换同D题,然后就是裸的KMP了

  1. #include <map>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7.  
  8. const int maxn = ;
  9.  
  10. char str[], s[maxn], ma[maxn], ans[maxn];
  11.  
  12. int mp[maxn], l, len;
  13.  
  14. map <char, char> p;
  15.  
  16. void manacher() {
  17. l = ;
  18. ma[l ++] = '$';
  19. ma[l ++] = '#';
  20. for(int i = ;i < len;i ++)
  21. ma[l ++] = s[i], ma[l ++] = '#';
  22. ma[l] = ;
  23. int mx = , id = ;
  24. for(int i = ;i < l;i ++) {
  25. mp[i] = mx > i ? min(mp[ * id - i], mx - i) : ;
  26. while(ma[i + mp[i]] == ma[i - mp[i]]) mp[i] ++;
  27. if(i + mp[i] > mx) mx = i + mp[i], id = i;
  28. }
  29. }
  30.  
  31. int main() {
  32. while(~scanf("%s %s", str, s)) {
  33. len = strlen(s);
  34. manacher();
  35. int leng = , pos = -;
  36. for(int i = ;i < l;i ++)
  37. if(mp[i] > leng)
  38. leng = mp[i], pos = i;
  39. leng --;
  40. if(leng == ) {
  41. puts("No solution!");
  42. continue;
  43. }
  44. if(pos & ) {
  45. printf("%d %d\n", pos / - leng / , pos / - leng / + leng - );
  46. for(int i = pos / - leng / , j = ;j <= leng;i ++, j ++)
  47. ans[j] = s[i];
  48. }
  49. else {
  50. printf("%d %d\n", pos / - leng / - , pos / - leng / + leng - );
  51. for(int i = pos / - leng / - , j = ;j <= leng;i ++, j ++)
  52. ans[j] = s[i];
  53. }
  54. ans[leng + ] = ;
  55. int dis = 'a' - str[];
  56. for(int i = ;i < ;i ++)
  57. p['a' + i] = 'a' + (i + dis + ) % ;
  58. for(int i = ;i <= leng;i ++)
  59. ans[i] = p[ans[i]];
  60. puts(ans + );
  61. }
  62. return ;
  63. }

bupt summer training for 16 #8 ——字符串处理的更多相关文章

  1. bupt summer training for 16 #7 ——搜索与DP

    https://vjudge.net/contest/174962#overview A.我们发现重点在于x,y只要累加就ok了 在每个x上只有上下两种状态,所以可以记忆化搜索 f[0/1][i]表示 ...

  2. bupt summer training for 16 #6 ——图论

    https://vjudge.net/contest/174020 A.100条双向边,每个点最少连2个边 所以最多100个点,点的标号需要离散化 然后要求恰好经过n条路径 快速幂,乘法过程就是flo ...

  3. 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 ...

  4. bupt summer training for 16 #4 ——数论

    https://vjudge.net/contest/173277#overview A.平方差公式后变为 n = (x + y)(x - y) 令 t = x - y ,变成 n = (t + 2x ...

  5. bupt summer training for 16 #3 ——构造

    https://vjudge.net/contest/172464 后来补题发现这场做的可真他妈傻逼 A.签到傻逼题,自己分情况 #include <cstdio> #include &l ...

  6. bupt summer training for 16 #2 ——计算几何

    https://vjudge.net/contest/171368#overview A.一个签到题,用叉积来判断一个点在一条线的哪个方向 可以二分,数据范围允许暴力 #include <cst ...

  7. bupt summer training for 16 #1 ——简单题目

    D.What a Mess 给n个数,求其中能满足 a[i] % a[j] == 0 的数对之和 n = 1W,max_ai = 100W 不是很大,所以就直接筛就可以了 计算可得最高复杂度 < ...

  8. leecode刷题(16)-- 字符串转换整数

    leecode刷题(16)-- 字符串转换整数 字符串转换整数 描述: 请你来实现一个 atoi 函数,使其能将字符串转换成整数. 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格 ...

  9. GUID转换成16位字符串或19位唯一字符串

    整理几个经常使用GUID转换成16位字符串或19位唯一字符串方法: /// <summary> /// 依据GUID获取16位的唯一字符串 /// Author : 付义方 /// < ...

随机推荐

  1. 让DIV在屏幕上下左右居中

    转自:http://blog.sina.com.cn/s/blog_65d41dff0100v0iz.html 其实解决的思路是这样的:首们需要position:absolute;绝对定位.而层的定位 ...

  2. Scikit-learn库中的数据预处理(一)

    数据标准化:当单个特征的样本取值相差甚大或明显不遵从高斯正态分布时,标准化表现的效果较差.实际操作中,经常忽略特征数据的分布形状,移除每个特征均值,划分离散特征的标准差,从而等级化,进而实现数据中心化 ...

  3. P3202 [HNOI2009]通往城堡之路 神仙题

    这个题不是坑人吗...写个tarjan标签,然后拿这么个神仙题来搞...代码有点看不懂,有兴趣的可以去洛谷题解区看看,懒得想了. 题干: 题目描述 听说公主被关押在城堡里,彭大侠下定决心:不管一路上有 ...

  4. B4197 [Noi2015]寿司晚宴 状压dp

    这个题一开始想到了唯一分解定理,然后状压.但是显然数组开不下,后来想到每个数(n<500)大于19的素因子只可能有一个,所以直接单独存就行了. 然后正常状压dp就很好搞了. 题干: Descri ...

  5. codeforces educational round 25

    A 出题人不给样例解释...具体程序 #include<bits/stdc++.h> using namespace std; int n; ]; int main() { scanf() ...

  6. Android高级开发-布局渲染流程与优化

    CPU(中央处理器)与GPU(图像处理器) 主要是设计目标不同,针对不同的应用场景.多缓存多分支,适用于复杂的逻辑运算,主要负责Measure,Layout,Record,Execute的计算操作. ...

  7. 02-vue过滤器和键盘修饰符

    过滤器 概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化.过滤器可以用在两个地方:mustache 插值和 v-bind 表达式.过滤器应该被添加在 JavaScript 表达式的 ...

  8. docker容器如何安装vim

    mv /etc/apt/sources.list /etc/apt/sources.list.bak && \     echo "deb http://mirrors.16 ...

  9. [转]Linux 正则表达式详解

    转自:http://www.jb51.net/article/42989.htm 一.linux文本查找命令 在说linux正规表达式之前,还介绍下linux中查找文本文件常用的三个命令: 1.gre ...

  10. Java继承体系中this的表示关系

    在继承关系下,父类中的this关键字并不总是表示父类中的变量和方法.this关键字的四种用法如前文所述,列举如下. 1) this(paras…); 访问其他的构造方法 2) this.xxx; 访问 ...