Solution :
把每个串和它们的反转拉一起求一个后缀数组,然后枚举回文串的中心,往回文串两边尽可能添加串,这个过程可以记忆化,如果转移中发现了环说明长度可以无限大。
吐槽:刚开始写的RMQ有点问题,怒改为暴力求lcp然后就A了…10s…..这题好 但是数据有待加强…….
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <bitset>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iterator>
#include <vector>
#include <queue>
#include <set>
#include <map>
#define rep(i, x, y) for (int i = (x), _ = (y); i <= _; ++i)
#define down(i, x, y) for (int i = (x), _ = (y); i >= _; --i)
#define x first
#define y second
#define LX_JUDGE
using namespace std;
typedef long long LL;
template<typename T> inline void upMax(T & x, T y) { x < y ? x = y : 0; }
template<typename T> inline void upMin(T & x, T y) { x > y ? x = y : 0; }
template<typename T>
inline void read(T & x)
{
char c;
while ((c = getchar()) < '0' || c > '9') ;
for (x = c - '0'; (c = getchar()) >= '0' && c <= '9'; x = x * 10 + c - '0') ;
}
const LL inf = 1e15;
const int N = 2e5 + 3e4;
namespace suffixArray
{
int Sa[N], Rank[N], height[N];
int mn[N][19], Log[N], tot;
void suffixDa(char * r, int n, int m)
{
static int ws[N];
int i, j, p, *x = Rank, *y = height;
tot = n;
memset(ws, 0, sizeof(int) * m);
for (i = 0; i < n; ++i)
++ws[x[i] = r[i]];
for (i = 1; i < m; ++i)
ws[i] += ws[i - 1];
for (i = n - 1; ~i; --i)
Sa[--ws[x[i]]] = i;
for (j = p = 1; p < n; j <<= 1, m = p)
{
for (p = 0, i = n - j; i < n; ++i)
y[p++] = i;
for (i = 0; i < n; ++i) if (Sa[i] >= j)
y[p++] = Sa[i] - j;
memset(ws, 0, sizeof(int) * m);
for (i = 0; i < n; ++i)
++ws[x[i]];
for (i = 1; i < m; ++i)
ws[i] += ws[i - 1];
for (i = n - 1; ~i; --i)
Sa[--ws[x[y[i]]]] = y[i];
swap(x, y);
x[Sa[0]] = 0, p = 1;
for (i = 1; i < n; ++i)
x[Sa[i]] = (y[Sa[i - 1]] == y[Sa[i]] && y[Sa[i - 1] + j] == y[Sa[i] + j]) ? p - 1 : p++;
}
for (i = 0; i < n; ++i)
Rank[Sa[i]] = i;
for (i = p = 0; i < n - 1; ++i)
{
p ? --p : 0;
j = Sa[Rank[i] - 1];
while (r[i + p] == r[j + p])
++p;
height[Rank[i]] = p;
}
height[0] = height[1] = height[n] = 0;
rep (i, 2, n)
Log[i] = Log[i >> 1] + 1;
rep (i, 0, n - 1)
mn[i][0] = height[i];
rep (i, 0, Log[n] - 1)
{
rep (j, 0, n - (1 << (i + 1)) + 1)
mn[j][i + 1] = min(mn[j][i], mn[j + (1 << i)][i]);
}
}
int Lcp(int x, int y)
{
if (x == y)
return tot - x;
x = Rank[x], y = Rank[y];
if (x > y)
swap(x, y);
int k = Log[y - x];
return min(mn[x + 1][k], mn[y - (1 << k) + 1][k]);
}
}
char str[N];
int belong[N], start[211], last[211];
int n, m;
LL f[N];
bool ins[N];
LL calc(int x)
{
using suffixArray::Lcp;
if (str[x] < 'a')
x = m;
if (ins[x])
return inf;
else if (f[x] > 0)
return f[x];
LL &ans = f[x];
ins[x] = 1;
if (x == m)
{
rep (i, 1, n + n)
upMax(ans, calc(start[i]));
}
else
{
int p = belong[x];
rep (j, (p <= n ? n + 1 : 1), (p <= n ? n + n : n))
{
int t = min(Lcp(x, start[j]), min(last[p] - x, last[j] - start[j]));
if (x + t == last[p])
upMax(ans, calc(start[j] + t) + t * 2);
else if (start[j] + t == last[j])
upMax(ans, calc(x + t) + t * 2);
else
upMax(ans, 2ll * t);
}
}
upMax(ans, 0ll), upMin(ans, inf);
ins[x] = 0;
return ans;
}
int main()
{
#ifdef LX_JUDGE
freopen("in.txt", "r", stdin);
#endif
read(n);
rep (i, 1, n)
{
scanf("%s", str + m);
start[i] = m;
while (str[m])
belong[m++] = i;
last[i] = m;
str[m++] = 'a' - 1;
}
int cur = 0;
rep (i, n + 1, n + n)
{
start[i] = m;
while (str[cur] >= 'a')
{
belong[m] = i;
str[m++] = str[cur++];
}
last[i] = m;
str[m++] = str[cur++];
reverse(str + start[i], str + last[i]);
}
str[m++] = 0;
suffixArray::suffixDa(str, m, 128);
memset(f, -1, sizeof(f));
LL ans = calc(m);
rep (i, 1, n)
{
using suffixArray::Lcp;
for (int j = start[i], k = last[i + n] - 1; j < last[i]; ++j, --k)
{
int tmp = min(Lcp(j, k), min(last[i] - j, last[i + n] - k));
if (j + tmp == last[i])
upMax(ans, calc(k + tmp) + 2 * tmp - 1);
else if (k + tmp == last[i + n])
upMax(ans, calc(j + tmp) + 2 * tmp - 1);
else
upMax(ans, 2ll * tmp - 1);
}
for (int j = start[i] + 1, k = last[i + n] - 1; j < last[i]; ++j, --k)
{
int tmp = min(Lcp(j, k), min(last[i] - j, last[i + n] - k));
if (j + tmp == last[i])
upMax(ans, calc(k + tmp) + tmp * 2);
else if (k + tmp == last[i + n])
upMax(ans, calc(j + tmp) + tmp * 2);
else
upMax(ans, 2ll * tmp);
}
}
ans < inf ? printf("%lld\n", ans) : puts("Infinity");
return 0;
}