poj1226 (hash)

Click to open the question link


The main idea: For multiple sets of data, each set of n strings, find the longest X, so that for any one of the n strings, X or the reversed string of X
is its substring. (Just output the length of X)


Idea: It seems that KMP or suffix array can do this, but I am still used to hashing. In this question, you can first divide the length into two (obviously, if a certain length is satisfied
, then strings smaller than this length can also be found), so you may wish to record this length as len. Then, take the first string as the standard, and scan it to get the hash value of the substring of length len starting with i as the subscript in the string (may be marked as h1[i] ), and the corresponding hash value of its reversed string (may be recorded as h2[i]). At the same time, the hash values ​​of substrings of length len in the following strings can also be processed and placed in the container. Next, is

See if there is such an i, so that the n-1 containers corresponding to the remaining n-1 strings either contain h1[i] or h2[i]. If it is, len is OK, and the required length must be greater than or equal to len; otherwise, the required length is less than len.


code show as below:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.StringTokenizer;

class Reader {
	static BufferedReader reader;
	static StringTokenizer tokenizer;

	static void init(InputStream input) {
		reader = new BufferedReader(new InputStreamReader(input));
		tokenizer = new StringTokenizer("");
	}

	static String next() throws IOException {
		while (!tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}
}

public class Main {

	/**
	 * @param args
	 */
	static int t, n, cnt, len1;
	static char ch[][];
	static int hash1[], hashin[];
	static HashSet<Integer> hashSet[];
	static String str;
	static long mul = 100000007;
	static long monum = Integer.MAX_VALUE;
	static long mulnum;

	private static boolean isOk(int num) {
		hashSet = new HashSet[n + 1];
		for (int i = 1; i <= n; i++)
			hashSet[i] = new HashSet<Integer>();
		mulnum = 1;
		for (int i = 1; i <= num; i++)
			mulnum = (mulnum * mul) % monum;
		long v;
		for (int i = 2; i <= n; i++) {
			if (ch[i].length < num)
				return false;
			v = 0;
			for (int j = 0; j < num; j++)
				v = (v * mul + (long) ch[i][j]) % monum;
			hashSet[i].add((int) v);
			for (int j = num; j < ch[i].length; j++) {
				v = (v * mul + (long) ch[i][j]) % monum;
				v = ((v - mulnum * (long) ch[i][j - num]) % monum + monum)
						% monum
				hashSet[i].add((int) v);
			}
		}
		hash1 = new int[len1 + 1];
		hashin = new int[len1 + 1];
		v = 0;
		for (int i = 0; i < num; i++) {
			v = (v * mul + (long) ch[1][i]) % monum;
		}
		hash1[1] = (int) v;
		for (int i = num; i < len1; i++) {
			v = (v * mul + (long) ch[1][i]) % monum;
			v = ((v - mulnum * (long) ch[1][i - num]) % monum + monum) % monum;
			hash1[i - num + 2] = (int) v;
		}
		v = 0;
		for (int i = len1 - 1; i >= len1 - num; i--) {
			v = (v * mul + (long) ch[1][i]) % monum;
		}
		hashin[len1 - num + 1] = (int) v;
		for (int i = len1 - num - 1; i >= 0; i--) {
			v = (v * mul + (long) ch[1][i]) % monum;
			v = ((v - mulnus * (long) ch[1][i + num]) % monum + monum) % monum;
			hashin[i + 1] = (int) v;
		}
		boolean flag;
		for (int i = 1; i <= len1; i++) {
			flag = true;
			for (int j = 2; j <= n; j++)
				if ((!hashSet[j].contains(hash1[i]))
						&& (!hashSet[j].contains(hashin[i]))) {
					flag = false;
					break;
				}
			if (flag)
				return true;
		}
		return false;
	}

	private static void deal() {
		len1 = ch[1].length;
		int l = 0;
		int r = ch[1].length;
		if (n == 1) {
			System.out.println(r);
			return;
		}
		int mid;
		while (r - l > 1) {
			mid = (l + r) / 2;
			if (isOk(mid))
				l = mid;
			else
				r = mid;
		}
		if (isOk (r))
			System.out.println(r);
		else
			System.out.println((r - 1));
	}

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		Reader.init(System.in);
		t = Reader.nextInt();
		ch = new char[101][];
		for (int casenum = 1; casenum <= t; casenum ++)
			n = Reader.nextInt();
			for (int i = 1; i <= n; i++) {
				str = Reader.next();
				ch[i] = str.toCharArray();
			}
			deal();
		}
	}

}


Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326823988&siteId=291194637