HDU

来源:互联网 发布:mac软件怎么卸载 编辑:程序博客网 时间:2024/06/06 12:26

点击打开题目链接

Bazinga

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


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 (1in) such that there exists an integer j (1j<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 of ``ruizhang", and ``rzhang" is not a substring of ``ruizhang".
 

Input
The first line contains an integer t (1t50) which is the number of test cases.
For each test case, the first line is the positive integer n (1n500) 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
45ababczabcabcdzabcd4youlovinyouaboutlovinyouallaboutlovinyou5dedefabcdabcdeabcdef3abaccc
 

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

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

Recommend
wange2014
 

Statistic | Submit | Discuss | Note

题目大意:

给出n个字符串,找到最大的j使得从1->j-1中存在s[i]不是s[j]的子串。

思路:

如果直接枚举两个串复杂度为50*500*500=12500000,还不加匹配算法的复杂度,超时。
现在想可不可以剪枝。
两层循环,第一层i枚举所有子串,第二层j枚举母串。
如果s[i]是s[j]的子串,则s[i]串的贡献完全可以转化成s[j]串,则直接break到下一个子串.
如果s[i]串不是s[j]的子串,则s[j]串即为满足题目要求的,标记下来,以后遍历母串跳过s[j]即可。
然后遍历寻找最大的j即可。

KMP版代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 500 + 5;char s[maxn][2500];int t, n;int p[maxn], nxt[maxn][2500], len[maxn];void getNext(int t) {    int i, j;    j = nxt[t][0] = -1;    i = 0;    while(i < n) {        while(j != -1 && s[t][i] != s[t][j]) j = nxt[t][j];        nxt[t][++i] = ++j;    }}//判断s[v]是否包含s[u]int kmp(int v, int u) {    int i, j;    i = j = 0;    while(i < len[v]) {        while(j != -1 && s[v][i] != s[u][j]) j = nxt[u][j];        i++;j++;        if(j >= len[u]) {            return 1;        }    }    return 0;}int solve() {    memset(p,1,sizeof(p));    int ans = -1;    for(int i = 1; i < n; i++) {        for(int j = i + 1; j <= n; j++) {            if(p[j]) {                if(kmp(j, i)) break;                else {                    p[j] = 0;                    ans = max(ans, j);                }            }        }    }    return ans;}int main() {    scanf("%d", &t);    for(int kase = 0; kase < t; kase++) {        scanf("%d", &n);        for(int i = 1; i <= n; i++) {            scanf("%s", s[i]);            len[i] = strlen(s[i]);            getNext(i);        }        printf("Case #%d: %d\n",kase+1, solve());    }    return 0;}

看了别人的AC,才直到有strstr函数,可以寻找s[i]在s[j]串中的位置。

strstr版代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;using namespace std;const int maxn = 500 + 5;char s[maxn][2500];int t, n;int p[maxn];int solve() {    memset(p,1,sizeof(p));    int ans = -1;    for(int i = 1; i < n; i++) {        for(int j = i + 1; j <= n; j++) {            if(p[j]) {                if(strstr(s[j], s[i])) break;                else {                    p[j] = 0;                    ans = max(ans, j);                }            }        }    }    return ans;}int main() {    scanf("%d", &t);    int kase = 0;    while(t--) {        scanf("%d", &n);        for(int i = 1; i <= n; i++)             scanf("%s", s[i]);        printf("Case #%d: %d\n",++kase, solve());    }    return 0;}
原创粉丝点击