//注意java的contains并没有使用kmpimport java.util.*;
publicclassMain {publicstaticvoidmain(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");// }
}
}
privatestaticbooleanjudge(String str, String patternStr) {
int pai[] = newint[patternStr.length() + 1];//pai是模式p的后缀 pai[q]=max{k,k<q且pk是pq的后缀//算法导论}//pk 表示p[1...k]char pattern[] = newchar[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) {
returntrue;
} else {
returnfalse;
}
}
privatestaticbooleanmatchStr(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没有用returntrue;
//look another match//q=pai[q];
}
i++;
}
returnfalse;
}
privatestaticvoidcomputePai(int[] pai, char[] pattern) {
pai[1] = 0;
int k = 0;//k is pai[q-1] k+1 is pattern compare indexfor (int q = 2; q < pai.length; q++) {//pai[q-1]=wPkwhile (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;
}
publicvoidsetText(String text) {
this.text = text;
}
publicvoidsetPattern(String pattern) {
this.pattern = pattern;
}
publicbooleanKMPMatcher() {//匹配算法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];returntrue;
}
}
returnfalse;
// if (count == 0) {// System.out.println("There is no matcher!");// }
}
privateint[] computePrefix() {//前缀函数π计算int length = pattern.length();
int[] prefix = newint[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.
*/publicclassKMP {privatefinalint R; // the radixprivateint[][] dfa; // the KMP automotonprivatechar[] pattern; // either the character array for the patternprivate String pat; // or the pattern string/**
* Preprocesses the pattern string.
*
* @param pat the pattern string
*/publicKMP(String pat) {
this.R = 256;
this.pat = pat;
// build DFA from patternint m = pat.length();
dfa = newint[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
*/publicKMP(char[] pattern, int R) {
this.R = R;
this.pattern = newchar[pattern.length];
for (int j = 0; j < pattern.length; j++)
this.pattern[j] = pattern[j];
// build DFA from patternint m = pattern.length;
dfa = newint[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
*/publicintsearch(String txt) {
// simulate operation of DFA on textint 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; // foundreturn 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
*/publicintsearch(char[] text) {
// simulate operation of DFA on textint 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; // foundreturn 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
*/publicstaticvoidmain(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);
}
}