跳转至

字符串匹配

问题地址 https://www.acwing.com/problem/content/description/833/

由于ACMer选手在比赛中总是记不住KMP算法,特此记录一下使用哈希字符串来代替KMP算法,唯一的缺陷就是害怕出题人卡哈希值(131、13331)

KMP算法

kmp next数组(坐标1开始)

import java.io.*;
import java.util.*;
import java.lang.*;
import java.math.*;

public class Main {

    Scanner sin = new Scanner(System.in);
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer cin = new StreamTokenizer(in);
    PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));

    final int N = 100010, mod = (int) (1e9 + 7), inf = 0x3f3f3f3f;

    int nextInt() throws Exception {
        cin.nextToken();
        return (int) cin.nval;
    }

    String next() throws Exception {
        cin.nextToken();
        return cin.sval;
    }

    int n, m;
    String x, s;
    int[] next = new int[N];

    void kmp() {
        int i = 1, j = 0;
        next[1] = 0;
        while (i <= n) {
            if (j == 0 || x.charAt(i) == x.charAt(j))
                next[++i] = ++j;
            else
                j = next[j];
        }
    }

    void solve() throws Exception {
        n = Integer.parseInt(in.readLine());
        x = in.readLine();
        m = Integer.parseInt(in.readLine());
        s = in.readLine();
        x = ' ' + x;
        s = ' ' + s;

        kmp();

        int i = 1, j = 1;
        while (i <= m) {
            if (j == 0 || s.charAt(i) == x.charAt(j)) {
                i++;
                j++;
            } else {
                j = next[j];
            }
            if (j == n + 1) {
                cout.print(i - j + " ");
                j = next[j];
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Main cmd = new Main();
        cmd.solve();
        cmd.cout.close();
    }
}

Hash字符串

import java.io.*;
import java.util.*;
import java.lang.*;
import java.math.*;

public class Main {

    Scanner sin = new Scanner(System.in);
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer cin = new StreamTokenizer(in);
    PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));

    final int N = 100010, mod = (int)(1e9+7), inf = 0x3f3f3f3f;

    int nextInt() throws Exception {
        cin.nextToken();
        return (int) cin.nval;
    }

    String next() throws Exception {
        cin.nextToken();
        return cin.sval;
    }

    int n, m;
    String S, P;

    long base = 131;
    long[] p = new long[N * 10];
    long[] hp = new long[N];
    long[] hs = new long[N * 10];

    void init() {
        p[0] = 1;
        for (int i = 1; i <= Math.max(n, m); i ++) {
            if (i <= n) hp[i] = hp[i - 1] * base + P.charAt(i);
            if (i <= m) hs[i] = hs[i - 1] * base + S.charAt(i);
            p[i] = p[i - 1] * base;
        }
    }

    long hash(int l, int r) {
        return hs[r] - hs[l - 1] * p[r - l + 1];
    }

    void solve() throws Exception {

        n = Integer.parseInt(in.readLine());
        P = " " + in.readLine();

        m = Integer.parseInt(in.readLine());
        S = " " + in.readLine();

        init();

        for (int i = 1; n - 1 + i <= m; i ++) {
            if (hp[n] == hash(i, i + n - 1))
                cout.print(i - 1 + " ");
        }
    }

    public static void main(String[] args) throws Exception {
        Main cmd = new Main();
        cmd.solve();
        cmd.cout.close();
    }
}