zoukankan      html  css  js  c++  java
  • Hdu5510 Bazinga

    Description

    Ladies and gentlemen, please sit up straight.
    Don't tilt your head. I'm serious.
    For (n) given strings (S_{1},S_{2},cdots,S_{n}), labelled from (1) to (n), you should find the largest (i (1 le i le n)) such that there exists an integer (j (1 le j < i)) and (S_{j}) is not a substring of (S_{i}).
    A substring of a string (S_{i}) is another string that occurs in (S_{i}). For example, "ruiz" is a substring of "ruizhang", and "rzhang" is not a substring of "ruizhang".

    Input

    The first line contains an integer (t) ((1 le t le 50)) which is the number of test cases.
    For each test case, the first line is the positive integer (n) ((1le n le 500)) and in the following n lines list are the strings (S_{1},S_{2},cdots,S_{n}).
    All strings are given in lower-case letters and strings are no longer than (2000) letters.

    Output

    For each test case, output the largest label you get. If it does not exist, output (−1).

    Sample Input

    4
    5
    ab
    abc
    zabc
    abcd
    zabcd
    4
    you
    lovinyou
    aboutlovinyou
    allaboutlovinyou
    5
    de
    def
    abcd
    abcde
    abcdef
    3
    a
    ba
    ccc

    Sample Output

    Case #1: 4
    Case #2: -1
    Case #3: 4
    Case #4: 3

    开始做的姿势不对,想的是裸暴力或者什么ac自动机啊。。。。(I 'm so puny!!!)
    其实这题正解就是暴力的剪枝,想如果(S_{j})(S_{i})的子串((i > j)),那么对于(k > i),若(S_{i})(S_{k})的子串,那么(S_{j})一定也是(S_{k})的子串;如果不是(k)就可以更新答案,那么也就说明只需要匹配(i)而不要匹配(j),由此可以打个(vis)标记剪枝了。

    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    
    typedef long long ll;
    #define maxn (510)
    #define maxl (2010)
    #define rhl (5000011)
    #define xi (127)
    int T,N,len[maxn],mi[maxl],pre[maxn][maxl],ans;
    char s[maxl]; bool exist[maxn];
    
    inline bool find(int a,int b)
    {
    	for (int i = len[b];i <= len[a];++i)
    	{
    		int key = pre[a][i]-(ll)pre[a][i-len[b]]*(ll)mi[len[b]]%rhl;
    		if (key < 0) key += rhl; if (key == pre[b][len[b]]) return true;
    	}
    	return false;
    }
    
    int main()
    {
    	freopen("5510.in","r",stdin);
    	freopen("5510.out","w",stdout);
    	scanf("%d",&T); mi[0] = 1;
    	for (int i = 1;i <= 2000;++i) mi[i] = (mi[i-1]*xi)%rhl;
    	for (int Cas = 1;Cas <= T;++Cas)
    	{
    		printf("Case #%d: ",Cas);
    		memset(exist,false,sizeof(exist));
    		scanf("%d",&N); ans = 0;
    		for (int i = 1;i <= N;++i)
    		{
    			scanf("%s",s+1); len[i] = strlen(s+1);
    			for (int j = 1;j <= len[i];++j) pre[i][j] = (pre[i][j-1]*xi+s[j]-'a'+1)%rhl;
    			for (int j = i-1;j;--j)
    			{
    				if (exist[j]) continue;
    				if (find(i,j)) exist[j] = true; else ans = i;
    			}
    		}
    		if (ans) printf("%d
    ",ans); else puts("-1");
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    指针
    使用函数
    数组,切片和字典
    CUDA 进阶学习
    makefile 常用函数
    内存(RAM或ROM)和FLASH存储的真正区别总结
    射频,系带,调制解调器
    固态激光雷达
    毫米波雷达
    对比感知技术的硬件或者算法的关键技术指标
  • 原文地址:https://www.cnblogs.com/mmlz/p/5961244.html
Copyright © 2011-2022 走看看