HDU 5510 2015ACM-ICPC沈阳赛区现场赛B题

Bazinga

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3268 Accepted Submission(s): 1049

Problem Description
Ladies and gentlemen, please sit up straight.
Don’t tilt your head. I’m serious.
这里写图片描述

For n given strings S1,S2,⋯,Sn, labelled from 1 to n, you should find the largest i (1≤i≤n) such that there exists an integer j ( 1 ≤ j < i ) and Sj is not a substring of Si.

A substring of a string Si is another string that occurs in Si. For example, ruiz" is a substring ofruizhang”, and rzhang" is not a substring ofruizhang”.

Input
The first line contains an integer t (1≤t≤50) which is the number of test cases.
For each test case, the first line is the positive integer n (1≤n≤500) and in the following n lines list are the strings S1,S2,⋯,Sn.
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

Source
2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)

题意:
n个字符串,找到最大序号的字符串,满足存在比其序号小的字符串不是其子串

思路:
正常的KMP肯定T
所以我们要优化一下
不难发现,我们在判断字符串的时候,可以去除一下没必要重复判断的字符串,这样可以大量节约时间,如果s1.s2.s5是s6的子串,那么,s7只需要判断s6是否为其子串可以间接判断s1,s2,s5,所以用一个数组标记一下需要判断的序号即可
另外,strstr可以完美替代KMP在此题的作用

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<algorithm>
using namespace std;

char s[510][2010];
char s1[510][2010];
int main() {
    int T;
    int n;
    int cas = 1;
    scanf("%d", &T);
    while (T--) {
        memset(s1, 0, sizeof(s1));
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", s[i]);
        }
        int tmp = -1;
        int o = 1;
        strcpy(s1[1], s[1]);
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= o; j++) {
                if (strstr(s[i], s1[j]) == NULL) {
                    tmp = i;
                    strcpy(s1[++o], s[i]);
                    break;
                }
            }
            if (tmp != i) {
                strcpy(s1[1], s[i]);
                o = 1;
            }
        }
        printf("Case #%d: %d\n", cas++, tmp);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值