题意:给定模式字串长度和不同字符的个数,求一个长字符串的不同子串的个数
分析:刚开始做这个题目的时候,本来是想直接用HashSet做的,但是觉得一是不太可能这么水,二是可能空间也不一定够,所以就想啊想,想偏了。后来在discuss里面看到有直接用HashMap等水过的,我就试了试,还真能过。不过这种做法效率不高,实现也不难,所以就不说了。
另一种真正用上所有条件的方法就是Rabin-Karp算法做。通过将不同的字符表示成以d为进制数的d个数字,将每一个字符串表示成一个多位d进制的数t,对比不同字符串所产生的的t来判断两个字符串是否相等。同时在本题中也可以将t用于计算得出的hash的key值。下面是代码和注释
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 5 public class Poj1200 { 6 7 public static void main(String[] args) throws IOException { 8 // TODO Auto-generated method stub 9 10 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 String[] strArgs = br.readLine().split(" "); 12 13 boolean[] hash = new boolean[16000000]; 14 15 int N = Integer.parseInt(strArgs[0]); 16 int NC = Integer.parseInt(strArgs[1]); 17 18 int[] charToInt = new int[260];//保留一个字节,八位的空间0-256表示ansii码的值 19 20 int seed = 0; 21 String text = br.readLine(); 22 23 for(int i = 0;i<text.length();i++) 24 { 25 if(charToInt[text.charAt(i)]==0) 26 { 27 charToInt[text.charAt(i)] = seed++;//对每个新出现的字符赋予数字表示 28 }; 29 } 30 31 int index = 0; 32 int temp =0; 33 int t = 1; 34 for(int i = 0;i<N;i++) 35 { 36 temp = temp * NC + charToInt[text.charAt(i)];//计算第一个N位的字符串的NC精制数字表示 37 t *= NC;// 38 } 39 if(!hash[temp]) 40 { 41 hash[temp] = true; 42 index++; 43 } 44 45 int ilength = text.length()-N; 46 for(int i = 1;i<=ilength;i++) 47 { 48 temp = (temp*NC + charToInt[text.charAt( i + N-1)])%t;//去除temp的最高位,补上新偏移到的最低位 49 if(!hash[temp]) 50 { 51 hash[temp] = true; 52 index++; 53 } 54 } 55 System.out.println(index); 56 } 57 58 }
时间: 2024-10-12 20:41:46