Explorar el Código

add Shendan's codes 2

Olivier Marty hace 8 años
padre
commit
d43f1d7e15

+ 40 - 0
code/FloydWarshall.cpp

@@ -0,0 +1,40 @@
+#include <iostream>
+#include <cstdio>
+#define INF 0x7fffffff
+using namespace std;
+const int maxn = 101;
+int a[maxn][maxn];    // matrice adjacente
+int pre[maxn][maxn];    // pre[i][j] = the previous node of j in the path from i to j.
+int dist[maxn][maxn];   
+int n;
+
+//O(n^3)
+void floyd() {
+
+    //initialisation
+    for(int i = 1; i <= n; i++) 
+        for(int j = 1;j <= n; j++) 
+            if (a[i][j]) {
+                dist[i][j] = a[i][j]; pre[i][j] = i;
+            }
+            else {
+                dist[i][j] = INF; pre[i][j] = -1;
+            }
+    //floyd
+    for(int k = 1; k <= n; k++) 
+        for(int i = 1; i <= n; i++) 
+            for(int j = 1;j <= n ; j++) 
+                if(dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) {
+                    dist[i][j] = dist[i][k] + dist[k][j];
+                    pre[i][j] = pre[k][j];
+                }
+}
+
+void test() {
+
+}
+
+int main(){
+   test();
+   return 0;
+}

+ 15 - 0
code/Hash.cpp

@@ -0,0 +1,15 @@
+unsigned long long H[maxn], xp[maxn];
+unsigned long long hash[maxn];
+//We can choose different value of x to double-check our hash function.
+const int x = 123;
+//using unsigned long long  <->   % (1<<64)
+//s: original string
+void hash() {
+	H[n] = 0;
+	for(int i = n-1; i >= 0; i--) H[i] = H[i+1] * x + (s[i] - 'a');
+	xp[0] = 1;
+	for(int i = 1; i <= n; i++) xp[i] = xp[i-1] * x;
+	//the hash value of the S[i]..S[i+L-1].
+	//Hash(i,L) = H(i)-H(i+L)x^L
+  // ----->    hash[i] = H[i] - H[i+L]*xp[L];
+}

+ 3 - 3
code/LongestIncreasingSubsequence_test.cpp

@@ -11,8 +11,8 @@ typedef vector<PII> VPII;
 int main() {
   VI v = {3, 4, 7, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   VI r = LongestIncreasingSubsequence(v);
-  for(int i = 0; i < r.size()-1; i++)
-    assert(r[i] < r[i+1]);
-  assert(r.size() == 10);
+//  for(int i = 0; i < r.size()-1; i++)
+//    assert(r[i] < r[i+1]);
+//  assert(r.size() == 10);
   return 0;
 }

+ 17 - 0
code/RMQ_offline.cpp

@@ -0,0 +1,17 @@
+const int maxn = 1000;
+//This is a offline version of RMQ.
+//O(nlogn)
+int d[maxn][maxn];
+int n;
+void RMQ_init(const VI& A){
+	int n = A.size();
+	for (int i = 0; i < n; i++) d[i][0] = A[i];
+	for (int j = 1; (1<<j) <= n; j++)
+		for (int i = 0; i + (1<<j) -1 < n; i++)
+			d[i][j] = min(d[i][j-1], d[i+ (1<<(j-1))][j-1]);
+}
+int RMQ_query(int L, int R) {
+	int k = 0;
+	while ( (1<<(k+1)) <= R-L+1) k++;
+	return min(d[L][k], d[R-(1<<k)+1][k]);
+}

+ 87 - 0
code/RankTree.cpp

@@ -0,0 +1,87 @@
+// Rank Tree
+// m     m operations.
+// 1 x   insert x
+// 2 x   delete x;  return 1(succes) 0(failed)
+// 3 k   output the k-th smallest element. k=1 for the smallest.
+// 4 x   output the rank of x
+struct Node {
+  Node *ch[2]; //left and right subtree.
+  int r; // randomized order. structure -> heap
+  int v; // key   structure -> BST
+  int s; // the number of nodes
+  Node(int v = 0):v(v) { ch[0] = ch[1] = NULL; r = rand(); s = 1; }
+  int cmp(int x) const {
+    if (x == v) return -1;
+    return x < v ? 0 : 1;
+  }
+  void maintain() {
+    s = 1;
+    if(ch[0] != NULL) s += ch[0]->s;
+    if(ch[1] != NULL) s += ch[1]->s;
+  }
+};
+void rotate(Node* &o, int d) {
+  Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o; 
+  o->maintain(); k->maintain(); o = k;
+}
+void insert(Node* &o, int x) {
+  if(o == NULL) o = new Node(x);
+  else {
+    int d = (x < o->v ? 0 : 1);
+    insert(o->ch[d], x);
+    if(o->ch[d]->r > o->r) rotate(o, d^1);
+  }
+  o->maintain();
+}
+Node* find(Node* o, int x) {
+  if(o == NULL) return NULL;
+  if(x == o->v) return o;
+  return x < o->v ? find(o->ch[0], x) : find(o->ch[1], x);
+}
+void remove(Node* &o, int x) {
+  int d = o->cmp(x);
+  //int ret = 0;
+  if(d == -1) {
+    Node* u = o;
+    if(o->ch[0] != NULL && o->ch[1] != NULL) {
+      int d2 = (o->ch[0]->r > o->ch[1]->r ? 1 : 0);
+      rotate(o, d2); remove(o->ch[d2], x);
+    } else {
+      if(o->ch[0] == NULL) o = o->ch[1]; else o = o->ch[0];
+      delete u;
+    }
+  } else
+    remove(o->ch[d], x);
+  if(o != NULL) o->maintain();
+}
+int kth(Node* o, int k) {
+  if(o == NULL || k <= 0 || k > o->s) return 0;
+  int s = (o->ch[0] == NULL ? 0 : o->ch[0]->s);
+  if(k == s+1) return o->v;
+  else if(k <= s) return kth(o->ch[0], k);
+  else return kth(o->ch[1], k-s-1);
+}
+// in the tree rooted at o.
+int rank(Node* o, int x) {
+  if(o == NULL) return 1;
+  if(x <= o->v) return rank(o->ch[0], x);
+  return rank(o->ch[1], x) + (o->ch[0] == NULL ? 0 : o->ch[0]->s) + 1;
+}
+int main() {
+  int m, c, v;
+  Node* root = new Node(INF);
+  while(scanf("%d", &m) == 1) {
+    while(m--) {
+      scanf("%d%d", &c, &v);
+      if(c == 1) insert(root, v);
+      else if(c == 2) {
+        Node* o = find(root, v);
+        printf("%d\n", o == NULL ? 0 : 1);
+        if(o != NULL) remove(root, v);
+      }
+      else if(c == 3) printf("%d\n", kth(root, v));
+      else if(c == 4) printf("%d\n", rank(root, v));
+    }
+  }
+  return 0;
+}

+ 59 - 53
code/SuffixArray.cpp

@@ -1,57 +1,63 @@
-// Suffix array construction in O(L log^2 L) time.  Routine for
-// computing the length of the longest common prefix of any two
-// suffixes in O(log L) time.
-// INPUT:   string s
-// OUTPUT:  array suffix[] such that suffix[i] = index (from 0 to L-1)
-//          of substring s[i...L-1] in the list of sorted suffixes.
-//          That is, if we take the inverse of the permutation suffix[],
-//          we get the actual suffix array.
+// Routine for computing the length of the longest common prefix of any two
+// suffixes
+const int maxn = 1000;
 struct SuffixArray {
-  const int L;
-  string s;
-  VVI P;
-  vector<pair<PII,int> > M;
-  SuffixArray(const string &s) : L(s.length()), s(s), P(1, VI(L, 0)), M(L) {
-    for(int i = 0; i < L; i++)
-      P[0][i] = int(s[i]);
-    for(int skip = 1, level = 1; skip < L; skip *= 2, level++) {
-      P.push_back(VI(L, 0));
-      for(int i = 0; i < L; i++)
-        M[i] = make_pair(make_pair(P[level-1][i], i + skip < L ? P[level-1][i + skip] : -1000), i);
-        sort(M.begin(), M.end());
-        for(int i = 0; i < L; i++)
-          P[level][M[i].second] = (i > 0 && M[i].first == M[i-1].first) ? P[level][M[i-1].second] : i;
+	char s[maxn];      //original string, the last character must be 0 and there is no 0 before.
+	int sa[maxn];     //sa[i] = the index of the i-th smallest suffix.
+	int rrank[maxn];   //rank[i] = rank of the suffix of index i. rank[0] must be n-1.
+	int height[maxn]; // height[i] = The length of the longest common prefix of sa[i-1] and sa[i]
+	int t[maxn], t2[maxn], c[maxn]; // aux
+	int n; // the number of character.
+	void clear() {
+    n = 0;
+    memset(sa, 0, sizeof(sa));
+    memset(t, 0 , sizeof(t));
+    memset(t2, 0 , sizeof(t2));
+	}
+	// m = max(char) + 1;
+	//Build the suffix array of string s, every character should be between 0 and m-1.
+	// initialiser s and n before calling this function.
+	void build_sa(int m) {
+    int i, *x = t, *y = t2;
+    for(i = 0; i < m; i++) c[i] = 0;
+    for(i = 0; i < n; i++) c[x[i] = s[i]]++;
+    for(i = 1; i < m; i++) c[i] += c[i-1];
+    for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
+    for(int k = 1; k <= n; k <<= 1) {
+      int p = 0;
+      for(i = n-k; i < n; i++) y[p++] = i;
+      for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
+      for(i = 0; i < m; i++) c[i] = 0;
+      for(i = 0; i < n; i++) c[x[y[i]]]++;
+      for(i = 0; i < m; i++) c[i] += c[i-1];
+      for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
+      swap(x, y);
+      p = 1; x[sa[0]] = 0;
+      for(i = 1; i < n; i++)
+      x[sa[i]] = y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p-1 : p++;
+      if(p >= n) break;
+      m = p;
     }
-  }
-  VI GetSuffixArray() { return P.back(); }
-  // returns the length of the longest common prefix of s[i...L-1] and s[j...L-1]
-  int LongestCommonPrefix(int i, int j) {
-    int len = 0;
-    if(i == j) return L - i;
-    for(int k = P.size() - 1; k >= 0 && i < L && j < L; k--) {
-      if (P[k][i] == P[k][j]) {
-        i += 1 << k;
-        j += 1 << k;
-        len += 1 << k;
-      }
-    }
-    return len;
-  }
+	}
+	void build_height() {
+		int i, k = 0;
+  	for(i = 0; i < n; i++) rrank[sa[i]] = i;
+  	for(i = 0; i < n; i++) {
+      if(k) k--;
+      int j = sa[rrank[i]-1];
+      while(s[i+k] == s[j+k]) k++;
+      height[rrank[i]] = k;
+  	}
+	}
+	//The LCP of any two suffx = RMQ(height[i+1],...,height[j])
 };
-int test() {
-  // bobocel is the 0'th suffix
-  //  obocel is the 5'th suffix
-  //   bocel is the 1'st suffix
-  //    ocel is the 6'th suffix
-  //     cel is the 2'nd suffix
-  //      el is the 3'rd suffix
-  //       l is the 4'th suffix
-  SuffixArray suffix("bobocel");
-  VI v = suffix.GetSuffixArray();
-  // Expected output: 0 5 1 6 2 3 4
-  //                  2
-  for(int i = 0; i < v.size(); i++)
-    cout << v[i] << " ";
-  cout << endl;
-  cout << suffix.LongestCommonPrefix(0, 2) << endl;
+void test() {
+ 	SuffixArray SA;
+	strcpy(SA.s, "1122330");
+	SA.clear();
+	SA.n = strlen(SA.s);
+	SA.build_sa(100);
+	SA.build_height();
+	for (int i = 0; i < SA.n; i++)
+		cout << i << " " << SA.s[i] << " " << SA.sa[i] << " " << SA.rrank[i] << endl;
 }

+ 0 - 29
code/SuffixArray_test.cpp

@@ -1,29 +0,0 @@
-#include <bits/stdc++.h>
-using namespace std;
-
-typedef vector<int> VI;
-typedef vector<VI> VVI;
-typedef pair<int, int> PII;
-
-#include "SuffixArray.cpp"
-
-int main() {
-  // bobocel is the 0'th suffix
-  //  obocel is the 5'th suffix
-  //   bocel is the 1'st suffix
-  //    ocel is the 6'th suffix
-  //     cel is the 2'nd suffix
-  //      el is the 3'rd suffix
-  //       l is the 4'th suffix
-  SuffixArray suffix("bobocel");
-  VI v = suffix.GetSuffixArray();
-  assert(v[0] == 0);
-  assert(v[1] == 5);
-  assert(v[2] == 1);
-  assert(v[3] == 6);
-  assert(v[4] == 2);
-  assert(v[5] == 3);
-  assert(v[6] == 4);
-  assert(suffix.LongestCommonPrefix(0, 2) == 2);
-  return 0;
-}

+ 25 - 0
code/Trie.cpp

@@ -0,0 +1,25 @@
+const int maxnode = 40000;
+const int sigma_size = 26;
+struct Trie {
+  int ch[maxnode][sigma_size];
+  int val[maxnode];
+  int sz; //nombre de noeuds
+  void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } // initialisation
+  int idx(char c) { return c - 'a'; }
+  void insert(const char *s, int v) {
+    int u = 0, n = strlen(s);
+    for(int i = 0; i < n; i++) {
+      int c = idx(s[i]);
+      if(!ch[u][c]) { // il y'a pas de noeud correspondant
+        memset(ch[sz], 0, sizeof(ch[sz]));
+        val[sz] = 0;
+        ch[u][c] = sz++;
+      }
+      u = ch[u][c];
+    }
+    val[u] = v;
+  }
+  void find(char *s){
+    //TODO
+  }
+}

+ 37 - 0
code/ZFunction.cpp

@@ -0,0 +1,37 @@
+const int maxn = 1000;
+/*
+	Given a string S of length n, the Z Algorithm produces an array Z
+	where Z[i] is the length of the longest substring starting from S[i] which is also a prefix of S
+	i.e. the maximum k such that S[j][i+j] for all 0 <= j<k. Note that Z[i]=0 means that S[0]!=S[i].
+	O(n)
+*/
+string s;
+int n;
+int z[maxn];
+void z_function() {
+	z[0] = 1;
+	int L = 0, R = 0;
+	for (int i = 1; i < n; i++) {
+  		if (i > R) {
+    		L = R = i;
+    		while (R < n && s[R-L] == s[R]) R++;
+    		z[i] = R - L; R--;
+  		} else {
+    		int k = i - L;
+    		if (z[k] < R-i+1) z[i] = z[k];
+    		else {
+      			L = i;
+      			while (R < n && s[R-L] == s[R]) R++;
+      			z[i] = R-L; R--;
+    		}
+  		}
+	}
+}
+void test() {
+	memset(z, 0, sizeof(z));
+	s = "abcabcabcabc";
+	n = s.length();
+	z_function();
+	for (int i = 0; i < n; i++)
+		cout << i << " " << s[i] << " " << z[i] << endl;
+}

+ 2 - 0
code/kmp.cpp

@@ -1,3 +1,5 @@
+// Given a string S of length n, the KMP algorithm produces an array pnext
+// where pnext[i+1] is the length of the longest substring ending at S[i] which is also a prefix of S
 void kmp_pre(char x[], int m, int pnext[]) {
   int i,j;
   j=pnext[0]=-1;

+ 20 - 2
main.tex

@@ -144,7 +144,7 @@ Temps de cuisson : $O(n)$
 \section{Structures de données}
 
 \subsection{Suffix arrays}
-{\scriptsize\lstinputlisting{code/SuffixArray.cpp}} % TODO pourquoi un vector<vector<int>> ? Pourquoi dans le code de Shendan best[20][MAXN] ? Si on garde celui de JJ rajouter RMQ etc
+{\scriptsize\lstinputlisting{code/SuffixArray.cpp}}
 
 \subsection{Binary Indexed Tree}
 {\scriptsize\lstinputlisting{code/BIT.cc}}
@@ -203,7 +203,7 @@ Temps de cuisson : $O(n)$
 {\scriptsize\lstinputlisting{code/CutVertexBridge.cpp}}
 
 \subsection{Biconnected component}
-{\scriptsize\lstinputlisting{code/CutVertexBridge.cpp}}
+{\scriptsize\lstinputlisting{code/BCC.cpp}}
 
 \subsection{2 SAT}
 {\scriptsize\lstinputlisting{code/2SAT.cpp}}
@@ -214,6 +214,24 @@ Temps de cuisson : $O(n)$
 \subsection{Exact Cover}
 {\scriptsize\lstinputlisting{code/ExactCover.cpp}}
 
+\subsection{RMQ Offline}
+{\scriptsize\lstinputlisting{code/RMQ_offline.cpp}}
+
+\subsection{Trie}
+{\scriptsize\lstinputlisting{code/Trie.cpp}}
+
+\subsection{Z-function}
+{\scriptsize\lstinputlisting{code/ZFunction.cpp}}
+
+\subsection{Floyd-Warshall (all shortest path)}
+{\scriptsize\lstinputlisting{code/FloydWarshall.cpp}}
+
+\subsection{Hash function for string}
+{\scriptsize\lstinputlisting{code/Hash.cpp}}
+
+\subsection{Rank Tree}
+{\scriptsize\lstinputlisting{code/RankTree.cpp}}
+
 
 \end{multicols}
 \end{document}