Q686 重复叠加字符串匹配

给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1。

举个例子,A = "abcd",B = "cdabcdab"。

答案为 3, 因为 A 重复叠加三遍后为 “abcdabcdabcd”,此时 B 是其子串;A 重复叠加两遍后为"abcdabcd",B 并不是其子串。

注意:

AB 字符串的长度在1和10000区间范围内。

class Solution {
    public int repeatedStringMatch(String A, String B) {
        int n = B.length() / A.length() + 2;

        String full = "";
        for (int i = 0; i < n; i++)
            full += A;

        int t = KMP(B, full);
        if (t == -1) {
            return -1;
        } else {
            int k = (full.length() - t - B.length()) / A.length();
            return n - k;
        }
    }

    private int KMP(String sub, String full) {
        if (sub == null || full == null || sub.length() > full.length())
            return -1;

        char[] chs1 = sub.toCharArray();
        char[] chs2 = full.toCharArray();

        int[] next = getNext(chs1);

        int m = 0;
        int n = 0;
        while (m <chs1.length && n < chs2.length) {
            if (chs1[m] == chs2[n]) {
                m++;
                n++;
            } else if (next[m] == -1) {
                n++;
            } else {
                m = next[m];
            }
        }

        return m == chs1.length ? n - m : -1;
    }


    private int[] getNext(char[] chs) {
        if (chs == null || chs.length <= 0)
            return new int[]{};

        int[] next = new int[chs.length];
        next[0] = -1;
        int n = 2;
        int m = 0;

        while (n < next.length) {
            if (chs[n - 1] == chs[m])
                next[n++] = ++m;
            else if (m == 0) {
                next[n++] = 0;
            } else {
                m = next[m];
            }
        }

        return next;
    }
}
posted @ 2019-04-16 11:07  围城DDD  阅读(161)  评论(0编辑  收藏  举报