2015ACM/ICPC亚洲区沈阳站-重现赛 1002 Bazinga

http://acm.hdu.edu.cn/contests/contest_show.php?cid=645

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:
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

题意:给出n个串s,下标i为1~n,找到最大的i,满足存在一个s[j](1 <= j < i)是s[i]的子串(实际上就是找每个串后面的不包含该串的串的最大下标)。

利用KMP算法:可以求出每个串的Next数组,然后用KMP匹配每两个字符串,找到满足条件的最大下标。

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

const int N=1e4+10;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;

typedef long long LL;

char s[510][2010];
int Len[510], Next[510][2010]; ///Len数组保存每个字符串的长度

void Getnext(int x) ///求出每个字符串的Next数组,保存在Next二维数组中
{
    int i = 0, j = -1;

    Next[x][0] = -1;

    while (i <= Len[x])
    {
        if (j == -1 || s[x][j] == s[x][i])
        {
            i++;
            j++;

            Next[x][i] = j;
        }
        else j = Next[x][j];
    }
}

int main ()
{
    int T, k = 0, i, j, x, y, ans, n;

    scanf("%d", &T);

    while (T--)
    {
        scanf("%d", &n);

        ans = -1;
        k++;

        for (i = 1; i <= n; i++)
        {
            scanf("%s", s[i]);

            Len[i] = strlen(s[i]);
            Getnext(i);
        }

        for (i = 1; i < n; i++) ///这个双重for循环就是要找到子串不是s[i]的字符串的最大下标
        {
            for (j = i+1; j <= n; j++)
            {
                x = 0;
                for (y = 0; y < Len[j]; y++)
                {
                    while (s[i][x] != s[j][y] && x >= 0)
                        x = Next[i][x];

                    x++; ///如果两个字符串中的字符相等++

                    if (x == Len[i]) break; ///当等于长度时,说明s[i]在s[j]中匹配成功,那么s[j]这个字符串不满足条件
                }

                if (x == Len[i]) break;
                else ans = max(ans, j); ///如果不等于长度,说明匹配不成功,那么s[i]不是s[j]的子串,更新满足条件的最大下标
            }
        }

        printf("Case #%d: %d
", k, ans);
    }

    return 0;
}

 

原文地址:https://www.cnblogs.com/syhandll/p/4925754.html