source: CIVL/examples/loop_invariants/verifyThisUB/longestRepeatedSubstring/lrs.c

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/*
2Author: Yihao Yan
3
4Download LCP.zip from: http://fm2012.verifythis.org/challenges
5
6-----------------
7Problem background:
8
9Together with a suffix array, LCP can be used to solve interesting text
10problems, such as finding the longest repeated substring (LRS) in a text.
11
12A suffix array (for a given text) is an array of all suffixes of the
13text. For the text [7,8,8,6], the suffix array is
14[[7,8,8,6],
15 [8,8,6],
16 [8,6],
17 [6]]
18
19Typically, the suffixes are not stored explicitly as above but
20represented as pointers into the original text. The suffixes in a suffix
21array are sorted in lexicographical order. This way, occurrences of
22repeated substrings in the original text are neighbors in the suffix
23array.
24
25-----------------
26Verification task:
27
28Implement longest repeated substring function and verify that it does so correctly.
29
30-----------------
31Result:
32
33For all strings with length less than 5, the lrs function returns an index i and a length l.
34The verification shows that the sub string with length l starting from index i is repeated in
35the original string and also, there exists no repeated string with length greater than l. Therefore
36the implemented function lrs behaves correctly.
37
38-----------------
39command: minor changes
40*/
41
42#include <stdlib.h>
43#include <civlc.cvh>
44#include <assert.h>
45
46#pragma CIVL ACSL
47
48$input int N;
49$assume(N > 0);
50$input int X1[N];
51
52#define GT(x,y,arr) (\exists int t; 0 <= t && t < n && (x) + t < n && (y) + t <= n \
53 && (y + t == n || (arr)[(x)+t] > (arr)[(y)+t]) \
54 (\forall int k; 0 <= k && k < t ==> (arr)[(x)+k] == (arr)[(y)+k]) && \
55 )
56
57int lcp1(int *arr, int n, int x, int y) {
58 int l = 0;
59
60 /*@ loop invariant 0 <= l && l <= n;
61 @ loop invariant 0 <= x + l && x + l <= n;
62 @ loop invariant 0 <= y + l && y + l <= n;
63 @ loop invariant \forall int i; 0 <= i && i < l ==> arr[x+i]==arr[y+i];
64 @ loop assigns l;
65 @*/
66 while (x+l<n && y+l<n && arr[x+l]==arr[y+l]) {
67 l++;
68 }
69 return l;
70}
71
72/* returns:
73 * 0 if x and y points to the same suffix;
74 * poistive value if x "is greater than" y;
75 * negative value if x "is NO greater than" y;
76 */
77int compare(int *a, int n, int x, int y) {
78 if (x == y) return 0;
79
80 int l = lcp1(a, n, x, y);
81
82 if (x+l == n) return -1;
83 if (y+l == n) return 1;
84 if (a[x+l] < a[y+l]) return -1;
85 if (a[x+l] > a[y+l]) return 1;
86 return -2;
87}
88
89void sort(int *a, int n, int *data) {
90 for(int i = 1; i < n; i++) {
91 int comp = compare(a, n, data[i - 1], data[i]);
92
93 /*@ loop invariant 0 <= j && j <= i;
94 @ loop invariant \forall int k; j < k && k <= i ==> GT(k-1,k,data);
95 @ loop assigns j, comp, data[j-1 .. j];
96 @*/
97 for(int j = i; j > 0 && comp > 0;) {
98 // swap:
99 int tmp = data[j];
100
101 data[j] = data[j-1];
102 data[j-1] = tmp;
103 j--;
104 if (j > 0)
105 comp = compare(a, n, data[j - 1], data[j]);
106 }
107 }
108}
109
110int lcp2(int *a, int n, int index, int* suffixes) {
111 return lcp1(a,n,suffixes[index], suffixes[index-1]);
112}
113
114/**
115result[0]: index
116result[1]: length
117*/
118void lrs(int* a, int n, int *result) {
119 int suffixes[n];
120
121 for(int i=0; i<n; i++) {
122 suffixes[i] = i;
123 }
124 sort(a, n, suffixes);
125 for(int i=1; i<n; i++) {
126 int len = lcp2(a, n, i,suffixes);
127
128 if(len > result[1]) {
129 result[0] = suffixes[i];
130 result[1] = len;
131 }
132 }
133}
134
135int main(){
136 int* result = (int*)malloc(2* sizeof(int));
137
138 result[0] = 0;
139 result[1] = 0;
140 lrs(X1, N, result);
141
142 int index = result[0];
143 int maxLen = result[1];
144
145 if(N > 1) {
146 $assert($exists (int k | k >= 0 && k <= N - maxLen && k != index)
147 ($forall (int i: 0 .. maxLen-1) X1[k+i] == X1[index+i])
148 );
149 $assert(!($exists (int k | k >= 0 && k <= N - maxLen - 1)
150 ($exists (int j | j >= 0 && j <= N - maxLen - 1 && j != k)
151 ($forall (int i: 0 .. maxLen) X1[k+i] == X1[j+i])
152 )
153 )
154 );
155 }else{
156 $assert(index == 0 && maxLen == 0);
157 }
158
159 free(result);
160 return 0;
161}
Note: See TracBrowser for help on using the repository browser.