杭电acm 5510Bazinga(字符串)

Bazinga

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


Problem Description
Ladies and gentlemen, please sit up straight.
Don't tilt your head. I'm serious.
杭电acm 5510Bazinga(字符串)

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
 

Source
题意:输入n 然后输入n个字符串,求最大的i 要求1~i-1中有一个串不是i的子串?
想法:
先从后向前遍历每个字符串,每个字符串判断一下是否包含它前面一个字符串,找到i最大的不包含串。如果找不到,则为-1;否则用两个指针,p=i+1,q=i-1,每次判断q是否是p的子串,是的话q–,不是的话p++,直到有一方走到头位置。这样的理论复杂度为o(nm),m为字符串的总长度。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 505;
const int maxm = 2005;
int N, F[maxn];
char str[maxn][maxm];


int main ()
{
    int cas;
    scanf("%d", &cas);
    for (int kcas = 1; kcas <= cas; kcas++)
    {
        scanf("%d", &N);
        for (int i = 0; i < N; i++)
            scanf("%s", str[i]);
        int p = N-1;
        while (p && strstr(str[p], str[p-1]) != NULL)
            p--;
        p++;
        for (int i = p-2; i >= 0 && p < N; i--)
        {
            while (p < N && strstr(str[p], str[i]) == NULL)
            p++;
        }
        if (p == 1)
        p = -1;
        printf("Case #%d: %d\n", kcas, p);
    }
    return 0;
}
代码二:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef unsigned long long ULL;
#define SEED 1000000007
const int maxn = 2010;
const int N = 505;
int p[maxn], pos;
char s[N][maxn];
ULL k[maxn], Hash[maxn], hash_[maxn];
void init()
{
    k[0] = 1;
    for(int i = 1; i < maxn; i++)
        k[i] = k[i-1] * SEED;
}
bool Pa(int len)
{
    int id = p[pos-1];
    int L = strlen(s[id]);
    hash_[L] = 0;
    for(int i = L-1; i >= 0; i--)
        hash_[i] = hash_[i+1] * SEED + s[id][i]-'a'+1;
    for(int i = 0; i <=len-L; i++)
    {
        if(hash_[0] == Hash[i]-Hash[i+L]*k[L])
            return true;
    }
    return false;
}
int main()
{
    int T, n, len, ans;
    scanf("%d", &T);
    init();
    for(int cas = 1; cas <= T; cas++)
    {
        scanf("%d", &n);
        pos = 0;
        ans = -1;
        for(int i = 1; i <= n; i++)
        {
            scanf("%s", s[i]);
            len = strlen(s[i]);
            Hash[len] = 0;
            for(int j = len-1; j >= 0; j--)
                Hash[j] = Hash[j+1] * SEED + s[i][j]-'a'+1;
            while(pos)
            {
                if(Pa(len))
                    pos--;
                else
                {
                    ans = i;
                    break;
                }
            }
            p[pos++] = i;
        }
        printf("Case #%d: %d\n", cas, ans);
    }
    return 0;
}