先insert建树,一棵树三个属性分别是:儿子节点,结点标记,重叠出现次数(也就是cnt);后query查询子段(用后缀的cnt来表征)出现次数。
关于节点标记的记录,每一个结点都有一个26大小Trie类型的儿子数组,方便定义此节点的标记子母,同时数组类型用Trie也方便了后驱的更新。
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
private static void insert(final Trie root,String str){
int idx = 0 ;
//final变量修饰对象,配合对象的继承使用,达到只修改内容而不修改引用的目的
Trie cur = root ;
for(int i=0;i<str.length();i++){
idx = str.charAt(i) - 'a' ;
if(cur.child[idx]==null){
cur.child[idx] = new Trie() ;
}
cur = cur.child[idx] ;
cur.cnt++ ;
cur.ch = str.charAt(i) ;
}
}
private static int query(final Trie root,String str){
int idx = 0 ;
int count = 0 ;
Trie cur = root ;
for(int i=0;i<str.length();i++){
idx = str.charAt(i) - 'a' ;
if(cur.child[idx]==null)return 0 ;
cur = cur.child[idx] ;
count = cur.cnt ;
}
return count ;
}
public static void main(String[] args) {
Scanner scan = new Scanner(new BufferedInputStream(System.in)) ;
String str ;
Trie root = new Trie() ;
while(true){
str = scan.nextLine() ;
if(str.equals(""))break ;
insert(root,str) ;
}
while(scan.hasNext()){
str = scan.nextLine() ;
System.out.println(query(root,str)) ;
}
}
}
class Trie{
char ch ;
int cnt ;
//儿子数组类型用Trie,大小为26,方便标记并更新下一个结点
Trie[] child ;
//用构造器初始化
public Trie(){
cnt = 0 ;
child = new Trie[26] ;
}
}