郑大第九届校赛正式赛(1818: squee_spoon and his Cube VI)

1818: squee_spoon and his Cube VI

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 59  Solved: 15

Submit Status Web Board

Description

市面上最常见的魔方,是三阶魔方,英文名为Rubik's Cube,以魔方的发明者鲁比克教授的名字命名。另外,二阶魔方叫Pocket Cube,它只有2*2*2个角块,通常也就比较小;四阶魔方叫Revenge Cube,这是因为就算你好不容易复原了三阶魔方,四阶魔方也会向你“复仇”;而五阶魔方叫Professor Cube,人们认为只有专家才能够复原这么复杂的魔方。

作为ACM(A Cube Master),squee_spoon准备为九阶正十二面体魔方命名,此时他的脑中浮现出一个长长的字符串S,似乎可以作为魔方的英文名。但是问题没有那么简单,squee_spoon有n个不喜欢的短字符串a1~an,所以squee_spoon希望将九阶正十二面体魔方命名为S的最长子串T,在这个子串中,不能包含a1~an,即a1~an均不是T的子串。

Input

多组数据。

第一行,字符串S,长度不会超过10^5。

第二行,一个整数n,1<=n<=10。

接下来的n行,n个字符串a1~an,ai的长度不会超过10。

Output

对于每组数据,输出两个整数,分别是T的长度及其在原串S中的起始下标(下标从0开始,如果存在多解,输出最小的起始下标)。


题解: 题是好题,但是貌似少了一个条件,当不可能出现子串T,输出什么呢?

            我是用字符串哈希加尺取做的,代码还是挺好写的,应该还有其他做法,比如KMP,AC自动机,看到的聚聚们,分享下你们的做法呗?


AC代码:

package xdlove_acmer;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.*;

public class Main {

	static Scanner cin = new Scanner(System.in);
	static PrintWriter out = new PrintWriter(System.out);
	static int seed = 71;
	
	static void make_hash(long hash[],String s) {
		for(int i = 0; i < s.length(); i++) {
			hash[i] = 0;
			if(i > 0) hash[i] = hash[i - 1] * seed;
			hash[i] += s.charAt(i); 
		}
	}
	
	static void init(long base[],int n) {
		for(int i = 0; i < n; i++) {
			base[i] = 1; 
			if(i > 0) base[i] = base[i - 1] * seed;  
		}
	}
	
	static long get_hash_id(String s) {
		long ans = 0;
		for(int i = 0; i < s.length(); i++) {
			ans = ans * seed + s.charAt(i);
		}
		return ans;
	}
	
	static long Get_id(long hash[],long base[],int l,int r) {
		long ans = hash[r];
		if(l != 0) ans = hash[r] - hash[l - 1] * base[r - l + 1];
		return ans;
	}
	
	public static void main(String[] args) throws IOException {
		int[] mp;
		long[] hash,base;
		base = new long[100005];
		mp = new int[100005];
		init(base, 100001);
		while(cin.hasNext()) {
			Arrays.fill(mp, -1);
			String s = cin.next();
			hash = new long[s.length()];
			make_hash(hash, s);
			int n = cin.nextInt();
			while(n-- > 0) {
				String t = cin.next();
				long ans = get_hash_id(t);
				for(int i = 0; i < s.length(); i++) {
					int len = t.length() - 1;
					if(i + len < s.length() && ans == Get_id(hash, base, i, i + len)) {
						if(mp[i] == -1) mp[i] = i + len;
						else mp[i] = Math.min(mp[i], i + len); 
					}
				}
			}
			int L = 0,R = 0,Max = 0,v = -1;
			while(R < s.length()) {
				if(mp[R] != -1) {
					//System.out.println(L);
					if(mp[R] - L > Max) {
						Max = mp[R] - L;
						v = L;
					}
					//System.out.println("Max " + Max);
					L = R + 1;
					if(L > R) R = L - 1; 
				}
				R++;
			}
			if(R - L > Max) {
				Max = R - L;
				v = L;
			}
			System.out.println(Max + " " + v);
		}
	}
	
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值