Advertisement
Guest User

E

a guest
Sep 15th, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.29 KB | None | 0 0
  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileReader;
  5. import java.io.IOException;
  6. import java.io.InputStreamReader;
  7. import java.io.PrintWriter;
  8. import java.util.ArrayDeque;
  9. import java.util.ArrayList;
  10. import java.util.HashMap;
  11. import java.util.Random;
  12. import java.util.StringTokenizer;
  13.  
  14. public class E {
  15.    
  16.     public static void main(String[] args) {
  17.         FastReader scan = new FastReader();
  18.         PrintWriter out = new PrintWriter(System.out);
  19.         Task solver = new Task();
  20.         solver.solve(1, scan, out);
  21.         out.close();
  22.     }
  23.    
  24.     static class Task {
  25.         static long[][] exp;
  26.         static char[] s;
  27.         static long[] MOD = {(int) 1e9+7, (int) 1e9+9, (int) 1e9+23};
  28.         static long base = 27;;
  29.        
  30.         public void solve(int testNumber, FastReader scan, PrintWriter out) {
  31.             int n = scan.nextInt();
  32.             s = scan.next().toCharArray();
  33.            
  34.             exp = new long[s.length+1][MOD.length];
  35.             for(int i = 0; i <= s.length; i++) {
  36.                 for(int j = 0; j < MOD.length; j++) {
  37.                     if(i == 0) exp[i][j] = 1;
  38.                     else exp[i][j] = mult(exp[i-1][j], base, MOD[j]);
  39.                 }
  40.             }
  41.            
  42.             int low = 1, high = n/2, ans = 0;
  43.             while(low <= high) {
  44.                
  45.                 int mid = (low + high)/2;
  46.                 boolean ok = false;
  47.                 ArrayList<RollingHash> a = new ArrayList<>();
  48.                 HashMap<RollingHash, Integer> check = new HashMap<>();
  49.                 RollingHash curr = new RollingHash();
  50.                
  51.                 for(int i = 0; i < mid; i++) curr.addLast(s[i]-'a'+1);
  52.                 a.add(getCopy(curr));
  53.                 for(int i = mid; i < n; i++) {
  54.                     curr.pollFirst();
  55.                     curr.addLast(s[i]-'a'+1);
  56.                     a.add(getCopy(curr));
  57.                 }
  58.                
  59.                 for(int i = mid; i < a.size(); i++) {
  60.                     check.put(a.get(i), check.getOrDefault(a.get(i), 0) + 1);
  61.                 }
  62.                 for(int i = 0; i < a.size(); i++) {
  63.                     if(check.containsKey(a.get(i))) {
  64.                         ok = true;
  65.                         break;
  66.                     }
  67.                     if(check.isEmpty()) break;
  68.                     RollingHash toRemove = a.get(i+mid);
  69.                     int count = check.get(toRemove);
  70.                     if(count == 1) check.remove(toRemove);
  71.                     else check.put(toRemove, count-1);
  72.                 }
  73.                
  74.                 if(ok) {
  75.                     ans = mid;
  76.                     low = mid+1;
  77.                 }
  78.                 else high = mid-1;
  79.             }
  80.             out.println(ans);
  81.         }
  82.        
  83.         static RollingHash getCopy(RollingHash a) {
  84.             RollingHash res = new RollingHash();
  85.             res.size = a.size;
  86.             for(int i = 0; i < a.value.length; i++) {
  87.                 res.value[i] = a.value[i];
  88.             }
  89.             return res;
  90.         }
  91.        
  92.         static long mult(long a, long b, long mod) {
  93.             return ((a%mod)*(b%mod))%mod;
  94.         }
  95.         static long add(long a, long b, long mod) {
  96.             return (a%mod+b%mod)%mod;
  97.         }
  98.         static long sub(long a, long b, long mod) {
  99.             return (a%mod - b%mod + mod)%mod;
  100.         }
  101.        
  102.        
  103.         static class RollingHash {
  104.             int size = 0;
  105.             long[] value = new long[MOD.length];
  106.             ArrayDeque<Integer> check = new ArrayDeque<>();
  107.            
  108.             public void addFirst(int v) {
  109.                 for(int i = 0; i < value.length; i++) {
  110.                     value[i] = add(value[i], mult(v, exp[size][i], MOD[i]), MOD[i]);
  111.                 }
  112.                 check.addFirst(v);
  113.                 size++;
  114.             }
  115.            
  116.             public void addLast(int v) {
  117.                 for(int i = 0; i < value.length; i++) {
  118.                     value[i] = mult(value[i], base, MOD[i]);
  119.                     value[i] = add(value[i], v, MOD[i]);
  120.                 }
  121.                 check.addLast(v);
  122.                 size++;
  123.             }
  124.             public void pollFirst() {
  125.                 int v = check.pollFirst();
  126.                 for(int i = 0; i < value.length; i++) {
  127.                     value[i] = sub(value[i], mult(v, exp[size-1][i], MOD[i]), MOD[i]);
  128.                 }
  129.                 size--;
  130.             }
  131.            
  132.             @Override
  133.             public boolean equals(Object o) {
  134.                 if(!(o instanceof RollingHash)) return false;
  135.                 RollingHash o2 = (RollingHash) o;
  136.                 for(int i = 0; i < value.length; i++) {
  137.                     if(this.value[i] != o2.value[i]) return false;
  138.                 }
  139.                 return true;
  140.             }
  141.            
  142.             @Override
  143.             public int hashCode() {
  144.                 int res = 0;
  145.                 int mod = (int) 1e9 + 9;
  146.                 for(int i = 0; i < value.length; i++) {
  147.                     res += value[i]%mod;
  148.                     res %= mod;
  149.                 }
  150.                 return res;
  151.             }
  152.            
  153.             @Override
  154.             public String toString() {
  155.                 String res = "";
  156.                 for(long i : value) res += i + " ";
  157.                 return res;
  158.             }
  159.         }
  160.     }
  161.    
  162.     static void shuffle(int[] a) {
  163.         Random get = new Random();
  164.         for(int i = 0; i < a.length; i++) {
  165.             int r = get.nextInt(a.length);
  166.             int temp = a[i];
  167.             a[i] = a[r];
  168.             a[r] = temp;
  169.         }
  170.     }
  171.    
  172.     static void shuffle(long[] a) {
  173.         Random get = new Random();
  174.         for(int i = 0; i < a.length; i++) {
  175.             int r = get.nextInt(a.length);
  176.             long temp = a[i];
  177.             a[i] = a[r];
  178.             a[r] = temp;
  179.         }
  180.     }
  181.    
  182.  
  183.     static class FastReader {
  184.         BufferedReader br;
  185.         StringTokenizer st;
  186.  
  187.         public FastReader() {
  188.             br = new BufferedReader(new InputStreamReader(System.in));
  189.         }
  190.         public FastReader(String s) throws FileNotFoundException {
  191.             br = new BufferedReader(new FileReader(new File(s)));
  192.         }
  193.  
  194.         String next() {
  195.             while (st == null || !st.hasMoreElements()) {
  196.                 try {
  197.                     st = new StringTokenizer(br.readLine());
  198.                 } catch (IOException e) {
  199.                     e.printStackTrace();
  200.                 }
  201.             }
  202.             return st.nextToken();
  203.         }
  204.  
  205.         int nextInt() {
  206.             return Integer.parseInt(next());
  207.         }
  208.  
  209.         long nextLong() {
  210.             return Long.parseLong(next());
  211.         }
  212.  
  213.         double nextDouble() {
  214.             return Double.parseDouble(next());
  215.         }
  216.  
  217.         String nextLine() {
  218.             String str = "";
  219.             try {
  220.                 str = br.readLine();
  221.             } catch (IOException e) {
  222.                 e.printStackTrace();
  223.             }
  224.             return str;
  225.         }
  226.     }
  227.  
  228. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement