KMP+滑动数组。
给你n个字符串,让你找编号i最大的一个字符串使得前i-1个字符串中至少有一个不是他的子串。
思路:左右一个i,一个j,当s[i]是s[j]的字串时++i,否则++j,并且记录当前j,当i==j时,两边都加。
记得用kmp优化。。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
char s[505][2005];
int f[505][2005];
void make_next(int id)
{
int len = strlen(s[id]);
for(int i = 1, k = 0; i < len; ++i)
{
while(k > 0 && s[id][k] != s[id][i])
k = f[id][k - 1];
if(s[id][k] == s[id][i])
++k;
f[id][i] = k;
}
}
bool is_sub(int ii, int jj)
{
int len1 = strlen(s[ii]);
int len2 = strlen(s[jj]);
if(len1 > len2)
return false;
for(int i = 0, k = 0; i < len2; ++i)
{
while(k > 0 && s[ii][k] != s[jj][i])
k = f[ii][k - 1];
if(s[ii][k] == s[jj][i])
{
++k;
}
if(k == len1)
return true;
if(k + len2 - i - 1 < len1)
return false;
}
return false;
}
int main()
{
int T;
int kase = 0;
scanf("%d", &T);
while(T--)
{
memset(f, 0, sizeof(f));
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i)
{
scanf("%s", s[i]);
}
for(int i = 0; i < n; ++i)
make_next(i);
int i = 0, j = 1;
int MAX = -1;
while(j < n)
{
if(is_sub(i, j))
{
++i;
if(i == j)
++j;
}
else
{
++j;
MAX = j;
}
}
printf("Case #%d: %d\n", ++kase, MAX);
}
}