【AC自动机+DP+大数】 POJ 1625 Censored!

估算了一下应该要用大数。。。以为用java会方便一点。。。结果发现还不如用C++大数。。。

import java.io.*;
import java.util.*;
import java.math.*;

class InputReader
{
	BufferedReader buf;
	StringTokenizer tok;
	InputReader()
	{
		buf = new BufferedReader(new InputStreamReader(System.in));
	}
	boolean hasNext()
	{
		while(tok == null || !tok.hasMoreElements()) {
			try{
				tok = new StringTokenizer(buf.readLine());
			} catch(Exception e) {
				return false;
			}
		}
		return true;
	}
	String next()
	{
		if(hasNext()) return tok.nextToken();
		return null;
	}
	int nextInt()
	{
		return Integer.parseInt(next());
	}
	long nextLong()
	{
		return Long.parseLong(next());
	}
	double nextDouble()
	{
		return Double.parseDouble(next());
	}
	BigInteger nextBigInteger()
	{
		return new BigInteger(next());
	}
	BigDecimal nextBigDecimal()
	{
		return new BigDecimal(next());
	}
}

class AC
{
	public static int next[][] = new int[505][55];
	public static int end[] = new int[505];
	public static int fail[] = new int[505];
	public static char s[] = new char[505];
	public static Queue<Integer> q = new LinkedList<Integer>();
	public static String ss;
	public static int top, now, root, n, f, r;
	public static int change[] = new int[1000];
	
	public static int newnode()
	{
		end[top] = 0;
		fail[top] = -1;
		for(int i = 0; i < n; i++) next[top][i] = -1;
		return top++;
	}
	
	public static void init()
	{
		top = 0;
		root = newnode();
		int len = ss.length();
		s = ss.toCharArray();
		for(int i = 0; i < len; i++) change[(int)(s[i]) + 200] = i;
	}
	
	public static int hash(int t)
	{
		return change[t];
	}
	
	public static void insert()
	{
		int len = ss.length();
		s = ss.toCharArray();
		now = root;
		for(int i = 0; i < len; i++) {
			int t = hash((int)(s[i]) + 200);
			if(next[now][t] == -1) next[now][t] = newnode();
			now = next[now][t];
		}
		end[now] = 1;
	}
	
	public static void build()
	{
		now = root;
		for(int i = 0; i < n; i++)
			if(next[now][i] == -1) next[now][i] = root;
			else {
				fail[next[now][i]] = root;
				q.add(next[now][i]);
			}
		while(!q.isEmpty()) {
			now = q.remove();
			end[now] |= end[fail[now]];
			for(int i = 0; i < n; i++) 
				if(next[now][i] == -1) next[now][i] = next[fail[now]][i];
				else {
					fail[next[now][i]] = next[fail[now]][i];
					q.add(next[now][i]);
				}
		}
	}
}

public class Main
{
	public static void main(String[] args)
	{
		//InputReader in = new InputReader();
		//BufferedReader in = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		PrintWriter out = new PrintWriter(System.out);
		BigInteger dp[][] = new BigInteger[55][505];
		AC ac = new AC();
		String ss[] = new String[10];
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));  
			ss = in.readLine().split(" ");
			int n = Integer.parseInt(ss[0]);
			int m = Integer.parseInt(ss[1]);
			int p = Integer.parseInt(ss[2]);
			ac.n = n;
			ac.ss = in.readLine();
			ac.init();
			for(int i = 0; i < p; i++) {
				ac.ss = in.readLine();
				ac.insert();
			}
			ac.build();
			
			for(int i = 0; i <= m; i++)
				for(int j = 0; j < ac.top; j++)
					dp[i][j] = BigInteger.ZERO;
			dp[0][0] = BigInteger.ONE;
			for(int i = 0; i < m; i++)
				for(int j = 0; j < ac.top; j++)
					for(int k = 0; k < n; k++)
						if(ac.end[ac.next[j][k]] == 0)
							dp[i+1][ac.next[j][k]] = dp[i+1][ac.next[j][k]].add(dp[i][j]);
			BigInteger ans = BigInteger.ZERO;
			for(int i = 0; i < ac.top; i++) ans = ans.add(dp[m][i]);
			
			out.println(ans.toString());
		}
		catch(IOException e){  
        }  
		out.close();
	}
}


你可能感兴趣的:(poj)