• 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) }

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

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

     1 #include <queue>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 
     7 const int maxn = 500010;
     8 
     9 struct trie {
    10     int next[maxn][26], fail[maxn], end[maxn];
    11     int L, root;
    12     queue <int> q;
    13 
    14     int newnode() {
    15         for(int i = 0;i < 26;i ++)
    16             next[L][i] = -1;
    17         end[L] = 0;
    18         return L ++;
    19     }
    20 
    21     void clear() {
    22         L = 0;
    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 = 0;i < len;i ++) {
    33             c = idx(buf[i]);
    34             if(next[now][c] == -1)
    35                 next[now][c] = newnode();
    36             now = next[now][c];
    37         }
    38         end[now] ++;
    39     }
    40 
    41     void build() {
    42         for(int i = 0;i < 26;i ++) {
    43             if(next[root][i] == -1)
    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 = 0;i < 26;i ++) {
    54                 if(next[now][i] == -1)
    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 = 0, tmp;
    66         for(int i = 0;i < len;i ++) {
    67             tmp = now = next[now][idx(buf[i])];
    68             while(tmp != root) {
    69                 res += end[tmp];
    70                 end[tmp] = 0;
    71                 tmp = fail[tmp];
    72             }
    73         }
    74         return res;
    75     }
    76 };
    77 
    78 trie ac;
    79 
    80 int Case, n;
    81 
    82 char buf[1000010];
    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
    ", ac.query(buf));
    91     }
    92     return 0;
    93 }
    View Code

    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[1000010];
     8 
     9 int nex[1000010];
    10 
    11 int main() {
    12     int i, j, ans, len;
    13     while(~scanf("%s", s)) {
    14         len = strlen(s);
    15         nex[0] = -1;
    16         ans = 0;
    17         for(i = 1;i < len;i ++) {
    18             j = nex[i - 1];
    19             while(j >= 0 && s[j + 1] != s[i]) j = nex[j];
    20             if(s[j + 1] == s[i]) {
    21                 nex[i] = j + 1;
    22                 ans = max(ans, i - nex[i]);
    23             }
    24             else nex[i] = -1, ans = max(ans, i + 1);
    25         }
    26         printf("%d
    ", ans);
    27     }
    28     return 0;
    29 }
    View Code

    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[110][110], f[110];
     8 
     9 char s1[110], s2[110];
    10 
    11 int main() {
    12     while(~scanf("%s %s", s1 + 1, s2 + 1)) {
    13         n = strlen(s1 + 1);
    14         memset(dp, 0x3f, sizeof dp);
    15         for(int d = 1;d <= n;d ++)
    16             for(int i = 1;i + d - 1 <= n;i ++) {
    17                 int j = i + d - 1;
    18                 if(i == j) dp[i][i] = 1;
    19                 else if(j == i + 1) dp[i][j] = 2 - (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 + 1][j] - (s2[i] == s2[k + 1]));
    23                 }
    24             }
    25         for(int i = 1;i <= n;i ++) {
    26             f[i] = dp[1][i];
    27             if(s1[i] == s2[i]) f[i] = min(f[i - 1], f[i]);
    28             else 
    29                 for(int j = 1;j < i;j ++)
    30                     f[i] = min(f[i],  f[j] + dp[j + 1][i]);
    31         }
    32         printf("%d
    ", f[n]);
    33     }
    34     return 0;
    35 }
    View Code

    F.简单的字典树

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

    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 = 1000010;
     9 
    10 char str[3], 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 = 0;
    18     ma[l ++] = '$';
    19     ma[l ++] = '#';
    20     for(int i = 0;i < len;i ++)
    21         ma[l ++] = s[i], ma[l ++] = '#';
    22     ma[l] = 0;
    23     int mx = 0, id = 0;
    24     for(int i = 0;i < l;i ++) {
    25         mp[i] = mx > i ? min(mp[2 * id - i], mx - i) : 1;
    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 = 0, pos = -1;
    36         for(int i = 0;i < l;i ++)
    37             if(mp[i] > leng)
    38                 leng = mp[i], pos = i;
    39         leng --;
    40         if(leng == 1) {
    41             puts("No solution!");
    42             continue;
    43         }
    44         if(pos & 1) {
    45             printf("%d %d
    ", pos / 2 - leng / 2, pos / 2 - leng / 2 + leng - 1);
    46             for(int i = pos / 2 - leng / 2, j = 1;j <= leng;i ++, j ++)
    47                 ans[j] = s[i];
    48         }
    49         else {
    50             printf("%d %d
    ", pos / 2 - leng / 2 - 1, pos / 2 - leng / 2 + leng - 2);
    51             for(int i = pos / 2 - leng / 2 - 1, j = 1;j <= leng;i ++, j ++)
    52                 ans[j] = s[i];
    53         }
    54         ans[leng + 1] = 0;
    55         int dis = 'a' - str[0];
    56         for(int i = 0;i < 26;i ++)
    57             p['a' + i] = 'a' + (i + dis + 26) % 26;
    58         for(int i = 1;i <= leng;i ++)
    59             ans[i] = p[ans[i]];
    60         puts(ans + 1);
    61     }
    62     return 0;
    63 }
    View Code

    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 = 1000010;
     9 
    10 char str[3], 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 = 0;
    18     ma[l ++] = '$';
    19     ma[l ++] = '#';
    20     for(int i = 0;i < len;i ++)
    21         ma[l ++] = s[i], ma[l ++] = '#';
    22     ma[l] = 0;
    23     int mx = 0, id = 0;
    24     for(int i = 0;i < l;i ++) {
    25         mp[i] = mx > i ? min(mp[2 * id - i], mx - i) : 1;
    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 = 0, pos = -1;
    36         for(int i = 0;i < l;i ++)
    37             if(mp[i] > leng)
    38                 leng = mp[i], pos = i;
    39         leng --;
    40         if(leng == 1) {
    41             puts("No solution!");
    42             continue;
    43         }
    44         if(pos & 1) {
    45             printf("%d %d
    ", pos / 2 - leng / 2, pos / 2 - leng / 2 + leng - 1);
    46             for(int i = pos / 2 - leng / 2, j = 1;j <= leng;i ++, j ++)
    47                 ans[j] = s[i];
    48         }
    49         else {
    50             printf("%d %d
    ", pos / 2 - leng / 2 - 1, pos / 2 - leng / 2 + leng - 2);
    51             for(int i = pos / 2 - leng / 2 - 1, j = 1;j <= leng;i ++, j ++)
    52                 ans[j] = s[i];
    53         }
    54         ans[leng + 1] = 0;
    55         int dis = 'a' - str[0];
    56         for(int i = 0;i < 26;i ++)
    57             p['a' + i] = 'a' + (i + dis + 26) % 26;
    58         for(int i = 1;i <= leng;i ++)
    59             ans[i] = p[ans[i]];
    60         puts(ans + 1);
    61     }
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    获取与端点的连接
    判断div内滚动条是否在底部
    MVC的使用!
    格式转换解决存取数据安全问题
    JQuery input file 上传图片
    contenteditable 常用的一些CSS !!
    C# 生成Json类型数据
    生成Excel
    生成验证码
    图片水印
  • 原文地址:https://www.cnblogs.com/ytytzzz/p/7275492.html
Copyright © 2020-2023  润新知