/*
* for each string, let dp[i] = the maximum length of a subsequence ending at i, for a string s
* we know that s will extend on a prefix of s, so let us search for all prefixes of s, and if the prefix matches the suffix
* we say that we can extend i to the dp of the prefix, and we implement this efficiently using hashing
*/
import java.io.*;
import java.util.*;
class savez {
static int n;
static int MOD = (int) 1e9 + 9, p = 31, maxN = (int) 2e6 + 5;;
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner();
PrintWriter out = new PrintWriter(System.out);
n = sc.nextInt();
int ans = 1;
HashMap<Integer, Integer> map = new HashMap();
for (int i = 0; i < n; i++) {
char[] s = sc.next().toCharArray();
int len = s.length;
int[] hash = new int[len];
long pow = 1;
long last = 0;
for (int j = 0; j < len; j++) {
last = last + (s[j] - 'A' + 1) * 1l * pow;
last %= MOD;
hash[j] = (int) last;
pow = pow * p % MOD;
}
int dp = 1;
pow = 1;
for (int prefix = len; prefix > 0; prefix--) {
int preHash = hash[prefix - 1], sufHash = hash[len - 1] - (prefix == len ? 0 : hash[len - 1 - prefix]);
if (sufHash < 0)
sufHash += MOD;
if (sufHash == (preHash * 1l * pow % MOD))
dp = Math.max(dp, 1 + map.getOrDefault(preHash, 0));
pow = pow * p % MOD;
}
map.put(hash[len - 1], dp);
ans = Math.max(ans, dp);
}
out.println(ans);
out.close();
}
static class Scanner {
BufferedReader br;
StringTokenizer st;
Scanner() {
br = new BufferedReader(new InputStreamReader(System.in));
}
Scanner(String fileName) throws FileNotFoundException {
br = new BufferedReader(new FileReader(fileName));
}
String next() throws IOException {
while (st == null || !st.hasMoreTokens())
st = new StringTokenizer(br.readLine());
return st.nextToken();
}
String nextLine() throws IOException {
return br.readLine();
}
int nextInt() throws IOException {
return Integer.parseInt(next());
}
long nextLong() throws NumberFormatException, IOException {
return Long.parseLong(next());
}
double nextDouble() throws NumberFormatException, IOException {
return Double.parseDouble(next());
}
}
}
Compilation message
Note: savez.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
75 ms |
9752 KB |
Output is correct |
2 |
Correct |
79 ms |
9716 KB |
Output is correct |
3 |
Correct |
81 ms |
9720 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
84 ms |
10020 KB |
Output is correct |
2 |
Correct |
80 ms |
9816 KB |
Output is correct |
3 |
Correct |
119 ms |
12024 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
312 ms |
39828 KB |
Output is correct |
2 |
Correct |
326 ms |
39032 KB |
Output is correct |
3 |
Correct |
336 ms |
39680 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
111 ms |
12276 KB |
Output is correct |
2 |
Correct |
286 ms |
27880 KB |
Output is correct |
3 |
Correct |
324 ms |
31728 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
362 ms |
33888 KB |
Output is correct |
2 |
Correct |
374 ms |
35160 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
359 ms |
34036 KB |
Output is correct |
2 |
Correct |
370 ms |
36088 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
371 ms |
38060 KB |
Output is correct |
2 |
Correct |
376 ms |
38060 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
386 ms |
43676 KB |
Output is correct |
2 |
Correct |
426 ms |
42828 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
426 ms |
50592 KB |
Output is correct |
2 |
Correct |
464 ms |
51812 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
530 ms |
51304 KB |
Output is correct |
2 |
Correct |
528 ms |
50320 KB |
Output is correct |
3 |
Correct |
419 ms |
48824 KB |
Output is correct |