版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/simon_world/article/details/40373063
AC 算法的一种实现(java版)
前言:
AC算法是最早也是最著名的多模式匹配算法。关于AC算法的讲解的文章很多,这里不再赘述。网上实现的大多数是用C或C++,现在给出java的实现。代码均为作者原创,仅供初学者参考,转载请注明出处。
代码实现:
package com.ac;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Queue;
public class Ac {
/**
* the member variable
*/
public final static int STATE = 1024;
public final static int CHARACTER = 26;
public static int[][] go;
public static String[] outPut;
public static int[] fail;
public static int curState;
private static PrintStream ps_goTo;
private static PrintStream ps_Output;
private static PrintStream ps_fail;
/**
*
* @param args test Ac
*/
public static void main(String[] args) {
goTo("Pattern.txt");
bulidFail();
acSearch();
}
/**
* to build goto
* @param filename Pattern.txt
*/
private static void goTo(String filename){
go = new int [STATE][CHARACTER];
outPut = new String[STATE];
for(int i = 0; i < STATE; i++) {
outPut[i] = new String("");
}
curState = 0;
try {
Scanner in = new Scanner(new File(filename));
while(in.hasNextLine()) {
String pattern = in.next();
if(!pattern.equals("\n")) {
char[] tempChar = pattern.toCharArray();
int curPattern = 0;
for(int i = 0; i < tempChar.length; i++) {
if(go[curPattern][hash(tempChar[i])] == 0) {
curState++;
go[curPattern][hash(tempChar[i])] = curState;
curPattern = curState;
} else {
curPattern = go[curPattern][hash(tempChar[i])];
}
}
outPut[curPattern] = new String(" " + pattern );
}
}
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File goTo = new File("goTo.txt");
try {
ps_goTo = new PrintStream(new FileOutputStream(goTo));
for(int i = 0; i < STATE; i++) {
for(int j = 0; j < CHARACTER; j++) {
if(go[i][j] != 0) {
String temp = "go[" + i + "]" + "[" + (char)(j + 97) + "]" + " = " + go[i][j];
ps_goTo.print(temp + "\n");
}
}
}
ps_goTo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* to bulid fail
*/
private static void bulidFail() {
Queue<Integer> queue = new LinkedList<Integer>();
fail = new int[STATE];
for(int i = 0; i < CHARACTER; i++) {
if(go[0][i] != 0) {
queue.add(go[0][i]);
fail[i] = 0;
}
}
while(!queue.isEmpty()) {
int r = queue.remove();
for(int i = 0; i < CHARACTER; i++) {
int state;
int s;
if(go[r][i] != 0) {
s = go[r][i];
queue.add(s);
state = fail[r];
fail[s] = go[state][i];
outPut[s] = outPut[s] + outPut[fail[s]];
}
}
}
File output = new File("Output.txt");
File Fail = new File("fail.txt");
try {
ps_Output = new PrintStream(new FileOutputStream(output));
ps_fail = new PrintStream(new FileOutputStream(Fail));
for(int i = 0; i <= curState; i++) {
if(!outPut[i].isEmpty()) {
String temp = "output[" + i +"] = " + outPut[i] + "\n";
ps_Output.print(temp);
}
}
for(int i = 1; i <= curState; i++){
String temp = "fail[" + i + "] = " + fail[i] + "\n";
ps_fail.print(temp);
}
ps_Output.close();
ps_fail.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static void acSearch() {
while(true) {
System.out.println("请选择功能:");
System.out.println("1.查询匹配");
System.out.println("2.退出");
String choose;
String pattern;
int state;
Scanner in = new Scanner(System.in);
choose = in.next();
switch(choose) {
case "1":
state = 0;
System.out.println("请输入要查询的字符串:");
pattern = in.next();
char[] temp = pattern.toCharArray();
for(int i = 0; i < pattern.length(); i++) {
if(go[state][hash(temp[i])] == 0) {
state = fail[state];
} else {
state = go[state][hash(temp[i])];
}
if(!outPut[state].equals("")) {
System.out.println("关键字出现的位置是:" + (i+1));
System.out.println("匹配的模式段是:" + outPut[state] + "\n");
}
}
break;
case "2":
in.close();
System.exit(0);
break;
default:
System.out.println("输入错误!");
System.exit(-1);
}
}
}
/**
* @param c the converting character
* @return int
*/
private static int hash(char c) {
if(c >= 65 && c <= 90 ) {
return c - 65;
} else if (c >= 97 && c <= 122) {
return c - 97;
}else {
return 0;
}
}
}