A. 文本校对

  • 暴力HASH就好了
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    const int N = 1e6 + 5, base = 19260817, mod = 998244353;
    int n, m, h[N], pw[N], inv[N], now[N];
    string s;
    ll qpow(int x, int y)
    {
    ll res = 0;
    while (y)
    {
    if (y & 1)
    res = res * x % mod;
    x = x * x % mod;
    y >>= 1;
    }
    return res;
    }
    void insert(int pos, int x)
    {
    string ss = " ";
    for (int i = 1; i < pos; i++)
    ss += s[i];
    ss += x;
    for (int i = pos; i <= n; i++)
    ss += s[i];
    for (int i = 1; i <= n; i++) {
    if (now[i] >= pos)
    now[i]++;
    }
    n++;
    s = ss;
    for (int i = 1; i <= n; i++)
    {
    h[i] = (h[i - 1] * base % mod + s[i] - 'a') % mod;
    }
    }
    int query(int l, int r)
    {
    return (h[r] - h[l - 1] * pw[r - l + 1] % mod + mod) % mod;
    }
    int check(int x, int i, int j)
    {
    return query(i, i + x - 1) == query(j, j + x - 1);
    }

    signed main()
    {
    IOS;
    cin >> s >> m;
    s = ' ' + s;
    n = s.size() - 1;
    pw[0] = 1;
    for (int i = 1; i < N; i++)
    {
    pw[i] = pw[i - 1] * base % mod;
    }
    for (int i = 1; i <= n; i++)
    {
    now[i] = i;
    h[i] = (h[i - 1] * base % mod + s[i] - 'a') % mod;
    }
    while (m--)
    {
    char op, x;
    cin >> op;
    if (op == 'I')
    {
    char x;
    int p;
    cin >> x >> p;
    p = min(p, n - 1);
    insert(p, x);
    }
    else
    {
    int i, j;
    cin >> i >> j;
    int l = 1, r = min(n - now[i] + 1, n - now[j] + 1), res = 0;
    while (l <= r)
    {
    int mid = (l + r) / 2;
    if (check(mid, now[i], now[j]))
    {
    l = mid + 1;
    res = mid;
    }
    else
    {
    r = mid - 1;
    }
    }
    cout << res << endl;
    }
    }

    return 0;
    }

B. 最长回文

  • 可以马拉车直接做
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    char chs[22000005];
    int p[22000005], cnt, ans;
    void manacher()
    {
    int mx = 0, mid = 0;
    for (int i = 0; i <= cnt; i++)
    {
    if (i < mx)
    {
    p[i] = min(mx - i, p[mid * 2 - i]);
    }
    else
    {
    p[i] = 1;
    }
    while (i + p[i] <= cnt && i - p[i] >= 0 && chs[i + p[i]] == chs[i - p[i]])
    {
    p[i]++;
    }
    if (i + p[i] > mx)
    {
    mx = i + p[i];
    mid = i;
    }
    ans = max(p[i], ans);
    }
    }
    int main()
    {
    int n;
    cin >> n;
    getchar();
    getchar();
    char ch = getchar();
    chs[0] = '#';
    while (ch >= 'a' && ch <= 'z')
    {
    chs[++cnt] = ch;
    chs[++cnt] = '#';
    ch = getchar();
    }
    manacher();
    printf("%d\n", ans - 1);
    return 0;
    }
  • 二分+HASH
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    typedef unsigned long long ull;
    typedef long long ll;
    constexpr int N = 1145141, base = 127;
    int n, ans;
    ull h[N], hRev[N], p[N];
    char s[N], sRev[N];
    ull getHashAll(char s[], int len) {
    ull ret = 0;
    for (int i = 1; i <= len; i++)
    ret = base * ret + (ull)s[i];
    return ret;
    }
    void getHashSeq(char s[], int len, ull h[]) {
    h[0] = 0;
    for (int i = 1; i <= len; i++)
    h[i] = h[i - 1] * base + s[i];
    }
    void getP(int len) {
    p[0] = 1;
    for (int i = 1; i <= len; i++)
    p[i] = p[i - 1] * base;
    }
    ull getSubHash(ull h[], int l, int r) {
    return h[r] - h[l - 1] * p[r - l + 1];
    }
    int main() {
    scanf("%d\n%s", &n, s + 1);
    for (int i = 1; i <= n; i++)
    sRev[n - i + 1] = s[i];
    getHashSeq(s, n, h);
    getHashSeq(sRev, n, hRev);
    getP(n + 1);

    for (int i = 1; i <= n; i++) {
    int l = 0, r = min(i - 1, n - i), mid;
    while (l <= r) {
    mid = (l + r) >> 1;
    if (getSubHash(h, i - mid, i - 1) == getSubHash(hRev, (n - i + 1) - mid, n - i)) {
    ans = max(ans, (mid << 1) | 1);
    l = mid + 1;
    } else
    r = mid - 1;
    }
    }
    for (int i = 1; i < n; i++) {
    int l = 1, r = min(i, n - i), mid;
    while (l <= r) {
    mid = (l + r) >> 1;
    if (getSubHash(h, i - mid + 1, i) == getSubHash(hRev, n - i + 1 - mid, n - i)) {
    ans = max(ans, mid << 1);
    l = mid + 1;
    } else
    r = mid - 1;
    }
    }
    printf("%d", ans);
    return 0;
    }

C. 二维匹配

  • 二维HASH
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    /*
    二维hash板子
    先对整体取哈希,把每个大小为 A×B 的存入 unordered_map;然后对每个子矩阵取哈希,判断是否在 map 中即可。时间复杂度 O(n^2)。
    g_{x, y​}=(a_{x, y​}+g_{x−1, y}​ × p2 + g_{x, y−1} ​× p1​ − g{x−1, y−1​} × p1 ​× p2​) mod p
    H(x1​​,y1​,x2​,y2​)=(H(1,1,x2​,y2​)−H(1,1,x1​−1,y2​)×p2x2​−x1​+1​−H(1,1,x2​,y1​−1)×p1y2​−y1​+1​+H(1,1,x1​−1,y1​−1)×p2x2​−x1​+1​×p1y2​−y1​+1​)modM​
    */
    #include<bits/stdc++.h>
    using namespace std;
    const int base1 = 131, base2 = 13331;
    long long n, m, q, a, b, mt[5010][5010], s[5010][5010], l1[5010], l2[5010];
    map<long long, bool> HASH;
    void handle(long long ll, long long rr) {
    for (int i = 1; i <= ll; i++) {
    for (int j = 1; j <= rr; j++) {
    char s;
    cin >> s;
    mt[i][j] = s - '0' + 1;
    }
    }
    for (int i = 1; i <= rr; i++) {
    l1[i] = l1[i - 1] * base1;
    l2[i] = l2[i - 1] * base2;
    }
    for (int i = 1; i <= ll; i++) {
    for (int j = 1; j <= rr; j++) {
    s[i][j] = s[i][j - 1] * base1 + mt[i][j];
    }
    }
    for (int i = 1; i <= ll; i++) {
    for (int j = 1; j <= rr; j++) {
    s[i][j] += s[i - 1][j] * base2;
    }
    }
    }
    int main() {
    l1[0] = l2[0] = 1;
    cin >> n >> m >> a >> b;
    handle(n, m);
    for (int i = a; i <= n; i++) {
    for (int j = b; j <= m; j++) {
    HASH[s[i][j] - s[i - a][j]*l2[a] - s[i][j - b]*l1[b] + s[i - a][j - b]*l2[a]*l1[b]] = 1;
    }
    }
    cin >> q;
    for (int k = 1; k <= q; k++) {
    handle(a, b);
    if (HASH[s[a][b]])cout << 1 << endl;
    else cout << 0 << endl;
    }
    return 0;
    }

  • 一个没优化过的AC自动机
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    int n, m, trie[410][26], fail[410], now, dep[410], state[410];
    bool late[410];
    queue<int> q;
    void insert(string s) {
    int len = s.length(), p = 0;
    for (int i = 0; i < len; i++) {
    if (!trie[p][s[i] - 'a'])
    trie[p][s[i] - 'a'] = ++now;
    dep[trie[p][s[i] - 'a']] = dep[p] + 1;
    p = trie[p][s[i] - 'a'];
    }
    late[p] = true;
    }
    void init() {
    for (int i = 0; i < 26; i++)
    if (trie[0][i])
    q.push(trie[0][i]);
    while (!q.empty()) {
    int x = q.front();
    q.pop();
    int Fail = fail[x];
    state[x] = state[Fail];
    if (late[x])
    state[x] |= (1 << dep[x]);
    for (int i = 0; i < 26; i++) {
    if (trie[x][i])
    fail[trie[x][i]] = trie[Fail][i], q.push(trie[x][i]);
    else
    trie[x][i] = trie[Fail][i];
    }
    }
    }
    int query(string t) {
    int len = t.length(), p = 0, ans = 0;
    unsigned predigit = 1;
    for (int i = 0; i < len; i++) {
    int tp = t[i] - 'a';
    p = trie[p][tp];
    predigit <<= 1;
    if (predigit & state[p])
    predigit |= 1, ans = max(ans, i + 1);
    }
    return ans;
    }
    int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
    string s;
    cin >> s;
    insert(s);
    }
    init();
    for (int i = 1; i <= m; i++) {
    string t;
    cin >> t;
    cout << query(t) << "\n";
    }
    return 0;
    }

F. 两段异或和

  • 01trie去找最大异或就好了
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    const int N=4e5+10;
    int n,tr[N*32][2],a[N],s[N],l[N],r[N],tot,ans;
    void insert(int x){
    int u=0;
    for(int i=30;i>=0;i--){
    int c=(x>>i)&1;
    if(!tr[u][c]) tr[u][c]=++tot;
    u=tr[u][c];
    }
    }
    int query(int x){
    int u=0,res=0;
    for(int i=30;i>=0;i--){
    int c=(x>>i)&1;
    if(tr[u][c^1]){
    res+=(1<<i);
    u=tr[u][c^1];
    }
    else u=tr[u][c];
    }
    return res;
    }
    signed main(){
    ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) s[i]=s[i-1]^a[i];
    insert(0);
    for(int i=1;i<=n;i++){
    l[i]=max(l[i-1],query(s[i]));
    insert(s[i]);
    }
    memset(tr,0,sizeof tr);
    tot=0;
    for(int i=n;i>=1;i--) s[i]=s[i+1]^a[i];
    insert(0);
    for(int i=n;i>=1;i--){
    r[i]=max(r[i+1],query(s[i]));
    insert(s[i]);
    }
    for(int i=1;i<n;i++) ans=max(ans,l[i]+r[i+1]);
    cout<<ans<<'\n';
    }