kmp

55 篇文章 0 订阅
//注意java的contains并没有使用kmp
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);


        while (sc.hasNext()) {
            String patternStr = sc.next();

            String str = sc.next();

            if (judge(str, patternStr)) {
                System.out.println("true");
            } else {
                System.out.println("false");
            }


//            KMP kmp = new KMP();
//            kmp.setText(str);
//            kmp.setPattern(patternStr);


//
//            if ( kmp.KMPMatcher()) {
//                System.out.println("true");
//            } else {
//                System.out.println("false");
//            }


//            if ( str.contains(patternStr)) {
//                System.out.println("true");
//            } else {
//                System.out.println("false");
//            }
        }


    }


    private static boolean judge(String str, String patternStr) {


        int pai[] = new int[patternStr.length() + 1];//pai是模式p的后缀 pai[q]=max{k,k<q且pk是pq的后缀//算法导论}//pk 表示p[1...k]

        char pattern[] = new char[patternStr.length() + 1];
        for (int i = 1; i < pattern.length; i++) {
            pattern[i] = patternStr.charAt(i - 1);//pattern[0]不使用
        }

        computePai(pai, pattern);
        boolean flag = matchStr(pai, str, pattern);

        if (flag) {
            return true;
        } else {
            return false;
        }


    }

    private static boolean matchStr(int[] pai, String str, char[] pattern) {


        int i = 0;
        int q = 0;

        while (i < str.length()) {

            while (q > 0 && str.charAt(i) != pattern[q + 1])//
            {
                q = pai[q];
            }

            if (str.charAt(i) == pattern[q + 1]) {

                q++;
            }

            if (q == pattern.length - 1) {//index=0没有用
                return true;
                //look another match
                //q=pai[q];

            }

            i++;

        }

        return false;


    }

    private static void computePai(int[] pai, char[] pattern) {

        pai[1] = 0;
        int k = 0;//k is pai[q-1]  k+1 is pattern compare index
        for (int q = 2; q < pai.length; q++) {//pai[q-1]=wPk
            while (k > 0 && pattern[k + 1] != pattern[q])//当pai*[q-1]不为空 ,pai[q]=1+max{pai*[q-1]}   否则pai[k]=0(即pai[1]=0)
            {
                k = pai[k];//k>pai[k]
            }
            //k=0 or pattern.charAt(k+1)=pattern.charAt(q)

            if (pattern[k + 1] == pattern[q])//p[k+1]=p[q]

            {
                k = k + 1;
            }

            pai[q] = k;

        }

    }


}

class KMP {

    private String text;
    private String pattern;

    KMP() {
    }

    KMP(String text, String pattern) {
        this.text = text;
        this.pattern = pattern;
    }

    public void setText(String text) {
        this.text = text;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }

    public boolean KMPMatcher() {//匹配算法
        int n = text.length();
        int m = pattern.length();

        int prefix[] = computePrefix();
        int q = 0;

        int count = 0;
        for (int i = 0; i < n; i++) {

            while (q > 0 && pattern.charAt(q) != text.charAt(i)) {
                q = prefix[q - 1];
            }

            if (pattern.charAt(q) == text.charAt(i))
                q++;

            if (q == m) {
//                System.out.println("Pattern occurs with shift  " + ++count + "times");
//                q = prefix[q - 1];

                return true;
            }
        }

        return false;

//        if (count == 0) {
//            System.out.println("There is no matcher!");
//        }
    }

    private int[] computePrefix() {//前缀函数π计算
        int length = pattern.length();
        int[] prefix = new int[length];

        prefix[0] = 0;

        int k = 0;
        for (int i = 1; i < length; i++) {
            while (k > 0 && pattern.charAt(k) != pattern.charAt(i)) {
                k = prefix[k - 1];
            }
            if (pattern.charAt(k) == pattern.charAt(i))
                k++;
            prefix[i] = k;
        }

        return prefix;
    }
}
/******************************************************************************
 *  Compilation:  javac KMP.java
 *  Execution:    java KMP pattern text
 *  Dependencies: StdOut.java
 *
 *  Reads in two strings, the pattern and the input text, and
 *  searches for the pattern in the input text using the
 *  KMP algorithm.
 *
 *  % java KMP abracadabra abacadabrabracabracadabrabrabracad
 *  text:    abacadabrabracabracadabrabrabracad 
 *  pattern:               abracadabra          
 *
 *  % java KMP rab abacadabrabracabracadabrabrabracad
 *  text:    abacadabrabracabracadabrabrabracad 
 *  pattern:         rab
 *
 *  % java KMP bcara abacadabrabracabracadabrabrabracad
 *  text:    abacadabrabracabracadabrabrabracad 
 *  pattern:                                   bcara
 *
 *  % java KMP rabrabracad abacadabrabracabracadabrabrabracad 
 *  text:    abacadabrabracabracadabrabrabracad
 *  pattern:                        rabrabracad
 *
 *  % java KMP abacad abacadabrabracabracadabrabrabracad
 *  text:    abacadabrabracabracadabrabrabracad
 *  pattern: abacad
 *
 ******************************************************************************/

/**
 *  The {@code KMP} class finds the first occurrence of a pattern string
 *  in a text string.
 *  <p>
 *  This implementation uses a version of the Knuth-Morris-Pratt substring search
 *  algorithm. The version takes time proportional to <em>n</em> + <em>m R</em>
 *  in the worst case, where <em>n</em> is the length of the text string,
 *  <em>m</em> is the length of the pattern, and <em>R</em> is the alphabet size.
 *  It uses extra space proportional to <em>m R</em>.
 *  <p>
 *  For additional documentation,
 *  see <a href="https://algs4.cs.princeton.edu/53substring">Section 5.3</a> of
 *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
 */
public class KMP {
    private final int R;       // the radix
    private int[][] dfa;       // the KMP automoton

    private char[] pattern;    // either the character array for the pattern
    private String pat;        // or the pattern string

    /**
     * Preprocesses the pattern string.
     *
     * @param pat the pattern string
     */
    public KMP(String pat) {
        this.R = 256;
        this.pat = pat;

        // build DFA from pattern
        int m = pat.length();
        dfa = new int[R][m]; 
        dfa[pat.charAt(0)][0] = 1; 
        for (int x = 0, j = 1; j < m; j++) {
            for (int c = 0; c < R; c++) 
                dfa[c][j] = dfa[c][x];     // Copy mismatch cases. 
            dfa[pat.charAt(j)][j] = j+1;   // Set match case. 
            x = dfa[pat.charAt(j)][x];     // Update restart state. 
        } 
    } 

    /**
     * Preprocesses the pattern string.
     *
     * @param pattern the pattern string
     * @param R the alphabet size
     */
    public KMP(char[] pattern, int R) {
        this.R = R;
        this.pattern = new char[pattern.length];
        for (int j = 0; j < pattern.length; j++)
            this.pattern[j] = pattern[j];

        // build DFA from pattern
        int m = pattern.length;
        dfa = new int[R][m]; 
        dfa[pattern[0]][0] = 1; 
        for (int x = 0, j = 1; j < m; j++) {
            for (int c = 0; c < R; c++) 
                dfa[c][j] = dfa[c][x];     // Copy mismatch cases. 
            dfa[pattern[j]][j] = j+1;      // Set match case. 
            x = dfa[pattern[j]][x];        // Update restart state. 
        } 
    } 

    /**
     * Returns the index of the first occurrrence of the pattern string
     * in the text string.
     *
     * @param  txt the text string
     * @return the index of the first occurrence of the pattern string
     *         in the text string; N if no such match
     */
    public int search(String txt) {

        // simulate operation of DFA on text
        int m = pat.length();
        int n = txt.length();
        int i, j;
        for (i = 0, j = 0; i < n && j < m; i++) {
            j = dfa[txt.charAt(i)][j];
        }
        if (j == m) return i - m;    // found
        return n;                    // not found
    }

    /**
     * Returns the index of the first occurrrence of the pattern string
     * in the text string.
     *
     * @param  text the text string
     * @return the index of the first occurrence of the pattern string
     *         in the text string; N if no such match
     */
    public int search(char[] text) {

        // simulate operation of DFA on text
        int m = pattern.length;
        int n = text.length;
        int i, j;
        for (i = 0, j = 0; i < n && j < m; i++) {
            j = dfa[text[i]][j];
        }
        if (j == m) return i - m;    // found
        return n;                    // not found
    }


    /** 
     * Takes a pattern string and an input string as command-line arguments;
     * searches for the pattern string in the text string; and prints
     * the first occurrence of the pattern string in the text string.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        String pat = args[0];
        String txt = args[1];
        char[] pattern = pat.toCharArray();
        char[] text    = txt.toCharArray();

        KMP kmp1 = new KMP(pat);
        int offset1 = kmp1.search(txt);

        KMP kmp2 = new KMP(pattern, 256);
        int offset2 = kmp2.search(text);

        // print results
        StdOut.println("text:    " + txt);

        StdOut.print("pattern: ");
        for (int i = 0; i < offset1; i++)
            StdOut.print(" ");
        StdOut.println(pat);

        StdOut.print("pattern: ");
        for (int i = 0; i < offset2; i++)
            StdOut.print(" ");
        StdOut.println(pat);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值