HackerRank チャレンジを解決しようとしていますが、問題が発生しています。明らかに、 O(n^2) のブルート フォース ソリューションは、パフォーマンス要件 (私が試した) の場合にはカットされないため、よりエレガントなソリューションを探し始めました。それが私がKMPに着陸したときです。そして、このチュートリアルに従って、私はそれを実装しました。
ただし、課題では、実際には文字列に 1 つの不一致を含めることができると記載されているため、コードにその機能を追加しようとしました。ただし、正しくない結果が得られており、その理由についてはまったくわかりません。誰かが私の解決策を見て、正しい方向に向けてください。
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
//This failure function creates an array of integers
//that indicate if there is a prefix that is both a
//prefix and a suffix of the word and at what position
//the prefix ends
private static int[] failureFunction(char[] p){
int i = 0;
int j = -1;
int len = p.length;
int[] f = new int[len+1];
f[i] = j;
int potentialWrong = 0;
while(i<len){
// if(j>=0 && p[i] != p[j]){
// potentialWrong++;
// }
// if(potentialWrong > 1){
// potentialWrong = 0;
while(j>=0 && p[i] != p[j]){
//if there is a mismatch consider the
//next widest border. The borders to be
//examined are obtained in decreasing order
// from the values f[i], f[f[i]] etc.
j=f[j];
}
// }
i++;
j++;
f[i]=j;
}
// for(int k : f){
// System.out.print(k+" ");
// }
return f;
}
private static LinkedList<Integer> searchKMP(char[] text, char[] ptrn){
int[] b = failureFunction(ptrn);
int j=0;
int i=0;
// pattern and text lengths
int ptrnLen = ptrn.length;
int txtLen = text.length;
int potentialWrong = 0;
LinkedList<Integer> list = new LinkedList<Integer>();
while(i<txtLen){
// System.out.println("i: "+i +", j: " +j);
if(text[i] != ptrn[j]){
potentialWrong++;
}
System.out.println("txt: " +text[i] +", ptrn: "+ptrn[j]);
System.out.println("Num wrong: " + potentialWrong);
if(potentialWrong > 1){
potentialWrong = 0;
while (j >= 0 && text[i] != ptrn[j]) {
j = b[j];
}
}
i++;
j++;
// a match is found
if (j == ptrnLen) {
list.add(i - ptrnLen);
j = b[j];
}
}
return list;
}
// private static boolean isValidMatch(String maybe, String virus){
// int numWrong = 0;
// // System.out.println(maybe +"vs."+ virus);
// for(int i=0;i<maybe.length();i++){
// if(maybe.charAt(i) != virus.charAt(i)){
// numWrong++;
// }
// if(numWrong > 1 ) return false;
// }
// return true;
// }
// private static LinkedList<Integer> getMatches(String patient, String virus){
// LinkedList<Integer> indices = new LinkedList<Integer>();
// for(int i=0;i<patient.length();i++){
// if(i+virus.length()-1 < patient.length()){
// if(isValidMatch(patient.substring(i, i+virus.length()), virus)){
// indices.add(i);
// }
// }
// else{
// break;
// }
// }
// return indices;
// }
public static void main(String[] args) {
Scanner scn = new Scanner(System.in);
int T = scn.nextInt();
String patient;
String virus;
for(int i =0;i<T;i++){
scn.nextLine(); //for empty line
patient = scn.nextLine();
virus = scn.nextLine();
LinkedList<Integer> list = searchKMP(patient.toCharArray(), virus.toCharArray());
for(int k : list){
System.out.print(k+" ");
}
System.out.println("");
}
}
}